#region usings using System.Collections.Generic; using System.Diagnostics; using OpenTK.Audio; using OpenTK.Graphics.OpenGL4; #endregion namespace SM.OGL { /// /// Specifies default object behaviour. /// public abstract class GLObject { private static readonly List _disposableObjects = new List(); private string _name = ""; /// /// Contains the OpenGL ID /// protected int _id = -1; /// /// This can mark the object to never report as compiled, even when it was. /// You can still figure out, if it was compiled by checking . If not -1, its compiled. /// Default: false /// protected bool ReportAsNotCompiled; /// /// This can prevent the object to compile. /// Default: true /// protected bool CanCompile = true; /// /// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1. /// Default: false /// protected virtual bool AutoCompile { get; set; } = false; /// /// Checks if the object was compiled. /// public bool WasCompiled => _id > 0 && !ReportAsNotCompiled; /// /// Names the object /// If is true, then it will also name the object in the system. /// public string Name { get => _name; set { _name = value; if (GLSystem.Debugging && WasCompiled) GL.ObjectLabel(TypeIdentifier, _id, _name.Length, _name); } } /// /// Returns the id for this object. /// It will auto compile, if needed and allowed. /// public virtual int ID { get { if (AutoCompile && !WasCompiled) PerformCompile(); return _id; } } /// /// Identifies the object. /// public abstract ObjectLabelIdentifier TypeIdentifier { get; } [DebuggerStepThrough] private void PerformCompile() { if (!CanCompile) return; Compile(); if (GLSystem.Debugging && string.IsNullOrEmpty(_name)) { try { GL.ObjectLabel(TypeIdentifier, _id, _name.Length, _name); } catch { // ignore } } } /// /// The action, that is called, when "ID" tries to compile something. /// [DebuggerStepThrough] public virtual void Compile() { } /// /// Is triggered, when something want to dispose this object. /// public virtual void Dispose() { _id = -1; } /// /// Re-compiles the object. /// public void Recompile() { if (!WasCompiled) return; Dispose(); Compile(); } /// public override string ToString() { return $"{GetType().Name} {(string.IsNullOrEmpty(_name) ? "" : $"\"{_name}\" ")}[{_id}]"; } /// /// This disposes the current objects, that where marked by the garbage collector. /// public static void DisposeMarkedObjects() { foreach (GLObject o in _disposableObjects) { o.Dispose(); } _disposableObjects.Clear(); } /// /// Returns the ID for the object. /// /// public static implicit operator int(GLObject glo) { return glo.ID; } /// /// If the garbage collector is trying to remove this object, it will add the object to a list, what get removed when is called. /// ~GLObject() { if (WasCompiled) _disposableObjects.Add(this); } } }