<commit_before>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.CompilerServices;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace Rs317.Sharp
{
	/// <summary>
	/// The Open GL through OpenTK game window for the game client.
	/// </summary>
	public sealed class OpenTKGameWindow : GameWindow, IImagePaintEventListener
	{
		private bool ViewportSizeChanged = false;

		private ConcurrentQueue<IOpenTKImageRenderable> ImageProducerCreationQueue { get; }

		private IInputCallbackSubscriber InputSubscriber { get; set; }

		private List<OpenGlRegisteredOpenTKImageRenderable> Renderables { get; }

		public OpenTKGameWindow(int width, int height)
			: base(width, height, new RsOpenTkGraphicsMocde(), "Rs317.Sharp by Glader")
		{
			ImageProducerCreationQueue = new ConcurrentQueue<IOpenTKImageRenderable>();
			Renderables = new List<OpenGlRegisteredOpenTKImageRenderable>(25);
			SetupGameEventCallbacks();
		}

		public void RegisterInputSubscriber(IInputCallbackSubscriber subscriber)
		{
			InputSubscriber = subscriber ?? throw new ArgumentNullException(nameof(subscriber));
		}

		private void SetupGameEventCallbacks()
		{
			//TODO: Reimplement mousedrag somehow.
			// this.DragDrop += new DragEventHandler(mouseDragged);

			this.MouseDown += new EventHandler<MouseButtonEventArgs>(mousePressed);
			this.MouseUp += new EventHandler<MouseButtonEventArgs>(mouseReleased);
			this.MouseMove += new EventHandler<MouseMoveEventArgs>(mouseMoved);
			this.KeyDown += new EventHandler<KeyboardKeyEventArgs>(keyPressed);
			this.KeyUp += new EventHandler<KeyboardKeyEventArgs>(keyReleased);
			this.KeyPress += new EventHandler<KeyPressEventArgs>(keyTyped);

			this.MouseEnter += new EventHandler<EventArgs>(mouseEntered);
			this.MouseLeave += new EventHandler<EventArgs>(mouseExited);
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			
			GL.ClearColor(Color.MidnightBlue);
			GL.Enable(EnableCap.Texture2D);

			RecalculateViewPort();
		}

		protected override void OnRenderFrame(FrameEventArgs e)
		{
			if(ViewportSizeChanged)
			{
				ViewportSizeChanged = false;

				RecalculateViewPort();
			}

			//All new image producers should have their OpenGL
			//data initialized
			//This should only be done ONCE per image producer, on creation.
			while (ImageProducerCreationQueue.TryDequeue(out var imageProducer))
			{
				int textureId = CreateTexture(imageProducer);
				Renderables.Add(new OpenGlRegisteredOpenTKImageRenderable(imageProducer, textureId));
			}

			//Now, for every renderable that we have registered
			//we just need to actually render it.
			foreach (var renderable in Renderables)
			{
				//TODO: Double check locking on isDirty
				//When the renderable is dirty, we must update
				//its representation in OpenGL
				if (renderable.Renderable.isDirty)
				{
					lock (renderable.Renderable.SyncObject)
					{
						//Renderable WILL still be dirty, definitely.
						//But now anything that attempts to set the dirty bit will have to wait.
						UpdateTexture(renderable);
						renderable.Renderable.ConsumeDirty();
					}
				}

				//TODO: Avoid calling beind again if we did update the texture. (it's already bound).
				//Regardless of the result we need to now render the image<commit_msg>Mitigate issue of rendering renderables that aren't active<commit_after>﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace Rs317.Sharp
{
	/// <summary>
	/// The Open GL through OpenTK game window for the game client.
	/// </summary>
	public sealed class OpenTKGameWindow : GameWindow, IImagePaintEventListener
	{
		private bool ViewportSizeChanged = false;

		private ConcurrentQueue<IOpenTKImageRenderable> ImageProducerCreationQueue { get; }

		private IInputCallbackSubscriber InputSubscriber { get; set; }

		private List<OpenGlRegisteredOpenTKImageRenderable> Renderables { get; }

		public OpenTKGameWindow(int width, int height)
			: base(width, height, new RsOpenTkGraphicsMocde(), "Rs317.Sharp by Glader")
		{
			ImageProducerCreationQueue = new ConcurrentQueue<IOpenTKImageRenderable>();
			Renderables = new List<OpenGlRegisteredOpenTKImageRenderable>(25);
			SetupGameEventCallbacks();
		}

		public void RegisterInputSubscriber(IInputCallbackSubscriber subscriber)
		{
			InputSubscriber = subscriber ?? throw new ArgumentNullException(nameof(subscriber));
		}

		private void SetupGameEventCallbacks()
		{
			//TODO: Reimplement mousedrag somehow.
			// this.DragDrop += new DragEventHandler(mouseDragged);

			this.MouseDown += new EventHandler<MouseButtonEventArgs>(mousePressed);
			this.MouseUp += new EventHandler<MouseButtonEventArgs>(mouseReleased);
			this.MouseMove += new EventHandler<MouseMoveEventArgs>(mouseMoved);
			this.KeyDown += new EventHandler<KeyboardKeyEventArgs>(keyPressed);
			this.KeyUp += new EventHandler<KeyboardKeyEventArgs>(keyReleased);
			this.KeyPress += new EventHandler<KeyPressEventArgs>(keyTyped);

			this.MouseEnter += new EventHandler<EventArgs>(mouseEntered);
			this.MouseLeave += new EventHandler<EventArgs>(mouseExited);
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			
			GL.ClearColor(Color.MidnightBlue);
			GL.Enable(EnableCap.Texture2D);

			RecalculateViewPort();
		}

		protected override void OnRenderFrame(FrameEventArgs e)
		{
			if(ViewportSizeChanged)
			{
				ViewportSizeChanged = false;

				RecalculateViewPort();
			}

			//All new image producers should have their OpenGL
			//data initialized
			//This should only be done ONCE per image producer, on creation.
			if (ImageProducerCreationQueue.TryDequeue(out var imageProducer))
			{
				//So, some producers may be created but not actually ready
				//for rendering purposes.
				//To avoid this issue we check if they are dirty.
				//If the queued image isn't dirty yet, then it's not ready to even be renderer.
				//We can requeue it and maybe handle it later.
				if (imageProducer.isDirty)
				{
					int textureId = CreateTexture(imageProducer);
					Renderables.Add(new OpenGlRegisteredOpenTKImageRenderable(imageProducer, textureId));
				}
				else
					ImageProducerCreationQueue.Enqueue(imageProducer);
			}

			//Now, for every renderable that we have registered
			//we just need to actually render it.
			foreach (var renderable in Renderables)
			{
				//TODO: Double check locking on isDirty
				//When the renderable is dirty, we must update
				//its representation in OpenGL
				if (renderable.Renderable.isDirty)
				{
					lock (renderable.Renderable.SyncObject)
					{
						//Renderable WILL still be dirty, definitely.
						//But now anything that attempts to set the dirty bit will have to wait.
						UpdateTexture(renderable);
						renderable.Renderable.ConsumeDirty();
					}
				}

				//TODO: Avoid calling beind again if we did update the texture. (it's already bound).
				//Regardless of the result we need to now render the image
{'fraction_non_alphanumeric': 0.08632700450758093, 'fraction_numerical': 0.002458680508127305, 'mean_word_length': 4.256281407035176, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2001408', 'n_tokens_mistral': 2467, 'n_tokens_neox': 2049, 'n_words': 579}