Esempio n. 1
0
        /// <summary>
        /// Creates the default shaders embedded into the binary.
        /// </summary>
        private void CreateDefaultShaders()
        {
            string defaultVert = Utilities.ReadEmbeddedResource("Emotion.Embedded.Shaders.DefaultVert.glsl");
            string defaultFrag = Utilities.ReadEmbeddedResource("Emotion.Embedded.Shaders.DefaultFrag.glsl");

            try
            {
                ShaderProgram.DefaultVertShader = new Shader(ShaderType.VertexShader, defaultVert);
                ShaderProgram.DefaultFragShader = new Shader(ShaderType.FragmentShader, defaultFrag);
            }
            catch (Exception ex)
            {
                // Check if one of the expected exceptions.
                if (new Regex("gl_arb_gpu_shader5").IsMatch(ex.ToString().ToLower()))
                {
                    Debugger.Log(MessageType.Warning, MessageSource.GL, "The extension GL_ARB_GPU_SHADER5 was found, but is not supported.");
                    Shader5ExtensionMissing = true;

                    // Cleanup erred ones if any.
                    ShaderProgram.DefaultVertShader?.Destroy();
                    ShaderProgram.DefaultFragShader?.Destroy();

                    // Recreate shaders.
                    ShaderProgram.DefaultVertShader = new Shader(ShaderType.VertexShader, defaultVert);
                    ShaderProgram.DefaultFragShader = new Shader(ShaderType.FragmentShader, defaultFrag);
                }
                else
                {
                    throw;
                }
            }

            Helpers.CheckError("making default shaders");
        }
Esempio n. 2
0
        /// <summary>
        /// Start running the engine loop. Can be blocking depending on the host.
        /// </summary>
        public static void Run()
        {
            // If the debugger is attached, don't wrap in a try-catch so that exceptions can be traced easier.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                InternalRun();
                return;
            }

            // If no debugger is attached, wrap in a try-catch so that exception logs are generated.
            try
            {
                InternalRun();
            }
            catch (Exception ex)
            {
                File.WriteAllText($"Logs{Path.DirectorySeparatorChar}FatalCrash_{DateTime.Now.ToFileTime()}", ex.ToString());
                Debugger.Log(MessageType.Error, MessageSource.Engine, $"Emotion engine has encountered a crash.\n{ex}");

                // Flush logs.
                while (Debugger.LogInProgress())
                {
                    Task.Delay(1).Wait();
                }

                // Close.
                Environment.Exit(1);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Is run every frame by the host.
        /// </summary>
        private static void LoopDraw(float frameTime)
        {
            // If not focused, or the renderer tells us not to render the frame - don't draw.
            if (!Host.Focused || !Renderer.RenderFrame())
            {
                Task.Delay(1).Wait();
                return;
            }

            // Run the thread manager.
            GLThread.Run();

            // Get frame time and increment total time.
            FrameTime  = frameTime;
            TotalTime += frameTime;

            // Clear the screen.
            Renderer.Clear();
            Helpers.CheckError("renderer clear");

            // Draw the layers.
            LayerManager.Draw();
            Helpers.CheckError("layer draw");

            // Finish rendering.
            Renderer.End();
            Helpers.CheckError("renderer end");

            // Draw debug.
            Debugger.Draw();

            // Swap buffers.
            Host.SwapBuffers();
        }
Esempio n. 4
0
 private void InitDebug()
 {
     Context.ScriptingEngine.Expose("debugAudio", (Action)(() =>
     {
         lock (_layers)
         {
             foreach (var layer in _layers)
             {
                 Debugger.Log(MessageType.Info, MessageSource.SoundManager, layer.ToString());
             }
         }
     }), "Dumps the status of the sound manager.");
 }
Esempio n. 5
0
        /// <summary>
        /// Prepare the Emotion engine.
        /// </summary>
        /// <param name="config">A function to apply initial settings.</param>
        public static void Setup(Action <Settings> config = null)
        {
            // Check if it was already setup.
            if (IsSetup)
            {
                throw new Exception("Context is already setup.");
            }
            IsSetup = true;

            // Initialize debugger so we have access to logging afterward.
            Debugger.Initialize();

            Debugger.Log(MessageType.Info, MessageSource.Engine, $"Starting Emotion v{Meta.Version}");

            // If the debugger is attached, don't wrap in a try-catch so that exceptions can be traced easier.
            if (Debugger.DebugMode)
            {
                InternalSetup(config);
                return;
            }

            // If no debugger is attached, wrap in a try-catch so that exception logs are generated.
            try
            {
                InternalSetup(config);
            }
            catch (Exception ex)
            {
                File.WriteAllText($"Logs{Path.DirectorySeparatorChar}InitCrash_{DateTime.Now.ToFileTime()}", ex.ToString());
                Debugger.Log(MessageType.Error, MessageSource.Engine, $"Emotion engine was unable to initialize.\n{ex}");

                // Flush logs.
                while (Debugger.LogInProgress())
                {
                    Task.Delay(1).Wait();
                }

                // Close.
                Environment.Exit(1);
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Is run every tick by the host.
        /// </summary>
        /// <param name="frameTime">The time between this tick and the last.</param>
        private static void LoopUpdate(float frameTime)
        {
            // Throttle so the whole CPU isn't used up by update cycles. Useful only when the Update loop runs on a separate thread.
            //Task.Delay(1).Wait();

            // Update debugger.
            Debugger.Update();

            // Update the renderer.
            Renderer.Update(frameTime);

            // If not rendering, then don't update user code.
            // The reason for this is because we are only skipping rendering when frame by frame mode is active, and the layer manager shouldn't trigger at all then.
            if (Renderer.RenderFrame() && Host.Focused)
            {
                LayerManager.Update();
            }

            // Run input. This is outside of a focus check so it can capture the first input when focus is claimed.
            InputManager.Update();
        }
Esempio n. 7
0
        /// <summary>
        /// WindowsNT bootstrap.
        /// </summary>
        private static void WindowsSetup()
        {
            // Set current directory to the process
            string processPath = AppDomain.CurrentDomain.BaseDirectory;

            if (processPath != Environment.CurrentDirectory + "\\")
            {
                Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
                Debugger.Log(MessageType.Warning, MessageSource.Engine, $"Process directory was wrong, set to: {Environment.CurrentDirectory}");
            }

            // Set the DLL path on Windows.
            string libraryDirectory = Environment.CurrentDirectory + "\\Libraries\\" + (Environment.Is64BitProcess ? "x64" : "x86");

            Windows.SetDllDirectory(libraryDirectory);
            string path = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);

            Environment.SetEnvironmentVariable("PATH", path + ";" + libraryDirectory, EnvironmentVariableTarget.Process);

            Debugger.Log(MessageType.Info, MessageSource.Engine, "Library Folder: " + libraryDirectory);
        }
Esempio n. 8
0
        internal Renderer()
        {
            // Renderer bootstrap.
            Debugger.Log(MessageType.Info, MessageSource.Renderer, "Loading Emotion OpenTK-GLES Renderer...");
            Debugger.Log(MessageType.Info, MessageSource.Renderer, "GL: " + GL.GetString(StringName.Version) + " on " + GL.GetString(StringName.Renderer));
            Debugger.Log(MessageType.Info, MessageSource.Renderer, "GLSL: " + GL.GetString(StringName.ShadingLanguageVersion));

            // Set execution flags, used for workarounding different GPU behavior.
            SetFlags();

            // Create default shaders. This also sets some shader flags.
            CreateDefaultShaders();

            // Create a default program, and use it.
            ShaderProgram defaultProgram = new ShaderProgram((Shader)null, null);

            defaultProgram.Bind();

            // Create objects.
            Camera      = new CameraBase(new Vector3(0, 0, 0), new Vector2(Context.Settings.RenderWidth, Context.Settings.RenderHeight));
            MatrixStack = new TransformationStack();

            // Setup main map buffer.
            _mainBuffer     = new QuadMapBuffer(MaxRenderable);
            _mainLineBuffer = new LineMapBuffer(MaxRenderable);

            // Check if the setup encountered any errors.
            Helpers.CheckError("renderer setup");

            // Setup additional GL arguments.
            GL.Enable(EnableCap.Blend);
            GL.DepthFunc(DepthFunction.Lequal);
            GL.Enable(EnableCap.DepthTest);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            // Setup debug.
            SetupDebug();
        }
Esempio n. 9
0
        private void SetFlags()
        {
            // Flag missing extensions.
            int  extCount = GL.GetInteger(GetPName.NumExtensions);
            bool found    = false;

            for (int i = 0; i < extCount; i++)
            {
                string extension = GL.GetString(StringNameIndexed.Extensions, i);
                if (extension.ToLower() != "gl_arb_gpu_shader5")
                {
                    continue;
                }
                found = true;
                break;
            }

            if (!found)
            {
                Debugger.Log(MessageType.Warning, MessageSource.GL, "The extension GL_ARB_GPU_SHADER5 was not found.");
                Shader5ExtensionMissing = true;
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Linux bootstrap.
        /// </summary>
        private static void LinuxSetup()
        {
            // Get the path of the process AKA where the engine was launched from.
            string processPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);

            if (processPath == null)
            {
                throw new Exception("Failed to get the process path.");
            }

            // Check if the process path is the current path.
            if (processPath != Environment.CurrentDirectory)
            {
                // Set the current path to the process path.
                Directory.SetCurrentDirectory(processPath);
                Unix.chdir(processPath);

                string processName    = Process.GetCurrentProcess().ProcessName;
                string executableName = processName.Replace(processPath + "/", "");

                Debugger.Log(MessageType.Warning, MessageSource.Engine, "It seems the process directory is not the executable directory. Will restart from correct directory.");
                Debugger.Log(MessageType.Warning, MessageSource.Engine, $"Proper directory is: {processPath}");
                Debugger.Log(MessageType.Warning, MessageSource.Engine, $"Executable is: {executableName}");

                // Stop the debugger so that the new instance can attach itself to the console and perform logging in peace.
                Debugger.Stop();

                // Restart the process.
                Process.Start(executableName)?.WaitForExit();
                Environment.Exit(0);
            }

            // Open libraries.
            Debugger.Log(MessageType.Warning, MessageSource.Engine, $"libsndio.so.6.1 found: {File.Exists("./Libraries/x64/libsndio.so.6.1")}");
            Unix.dlopen("./Libraries/x64/libsndio.so.6.1", Unix.RTLD_NOW);
        }
Esempio n. 11
0
        private static void InternalSetup(Action <Settings> config = null)
        {
            // Initiate bootstrap.
            Debugger.Log(MessageType.Info, MessageSource.Engine, "-------------------------------");
            Debugger.Log(MessageType.Info, MessageSource.Engine, $"Executed at: {Environment.CurrentDirectory}");
            Debugger.Log(MessageType.Info, MessageSource.Engine, $"Debug Mode / Debugger Attached: {Debugger.DebugMode} / {System.Diagnostics.Debugger.IsAttached}");
            Debugger.Log(MessageType.Info, MessageSource.Engine, $"64Bit: {Environment.Is64BitProcess}");
            Debugger.Log(MessageType.Info, MessageSource.Engine, $"OS: {CurrentPlatform.OS} ({Environment.OSVersion})");
            Debugger.Log(MessageType.Info, MessageSource.Engine, $"CPU: {Environment.ProcessorCount}");

            // Run platform specific boot.
            switch (CurrentPlatform.OS)
            {
            case PlatformName.Windows:
                WindowsSetup();
                break;

            case PlatformName.Linux:
                LinuxSetup();
                break;
            }

            Debugger.Log(MessageType.Info, MessageSource.Engine, "-------------------------------");
            Debugger.Log(MessageType.Info, MessageSource.Engine, "Bootstrap complete.");

            // Apply settings and run initial setup function.
            Settings initial = new Settings();

            config?.Invoke(initial);
            Settings = initial;

            // Setup thread manager.
            GLThread.BindThread();

            // Create host if not created.
            if (Host == null)
            {
                try
                {
                    Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating host...");
                    if (CurrentPlatform.OS == PlatformName.Windows || CurrentPlatform.OS == PlatformName.Linux || CurrentPlatform.OS == PlatformName.Mac)
                    {
                        Host = new OtkWindow();
                        Debugger.Log(MessageType.Info, MessageSource.Engine, "Created OpenTK window host.");
                    }
                    else
                    {
                        throw new Exception("Unsupported platform.");
                    }
                }
                catch (Exception ex)
                {
                    Debugger.Log(MessageType.Error, MessageSource.Engine, "Could not create host. Is the system supported?");
                    Debugger.Log(MessageType.Error, MessageSource.Engine, ex.ToString());
                    throw;
                }
            }

            // Apply settings and hook.
            Host.ApplySettings(Settings);
            Host.SetHooks(LoopUpdate, LoopDraw, Resize);

            // Start creating modules.

            // Scripting engine is first to provide the other modules the ability to expose functions.
            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating scripting engine...");
            ScriptingEngine = new ScriptingEngine();

            // Asset loader is next so other modules - especially the renderer, can access the file system.
            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating asset loader...");
            AssetLoader = new AssetLoader();

            // The order of the next modules doesn't matter.

            Debugger.InitializeModule();

            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating renderer...");
            Renderer = new Renderer();

            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating sound manager...");
            SoundManager = new SoundManager();

            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating layer manager...");
            LayerManager = new LayerManager();

            Debugger.Log(MessageType.Trace, MessageSource.Engine, "Creating input manager...");
            InputManager = new InputManager();
        }