diff --git a/docs/_static/css/algolia.css b/docs/_static/css/algolia.css
deleted file mode 100644
index d27f55e..0000000
--- a/docs/_static/css/algolia.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.wy-nav-side { overflow: visible; }
-.wy-side-scroll { overflow-x: inherit; }
-
-.algolia-autocomplete {
- display: block !important;
-}
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
index 7267e85..c90de39 100644
--- a/docs/_static/css/custom.css
+++ b/docs/_static/css/custom.css
@@ -1905,8 +1905,3 @@ p + .classref-constant {
padding: 3px 5px;
}
}
-
-/* Giscus */
-#godot-giscus {
- margin-bottom: 1em;
-}
diff --git a/docs/_static/js/custom.js b/docs/_static/js/custom.js
index bdc4a32..2d29ce2 100644
--- a/docs/_static/js/custom.js
+++ b/docs/_static/js/custom.js
@@ -1,431 +1,39 @@
-// Handle page scroll and adjust sidebar accordingly.
-
-// Each page has two scrolls: the main scroll, which is moving the content of the page;
-// and the sidebar scroll, which is moving the navigation in the sidebar.
-// We want the logo to gradually disappear as the main content is scrolled, giving
-// more room to the navigation on the left. This means adjusting the height
-// available to the navigation on the fly. There is also a banner below the navigation
-// that must be dealt with simultaneously.
-const registerOnScrollEvent = (function () {
- // Configuration.
-
- // The number of pixels the user must scroll by before the logo is completely hidden.
- const scrollTopPixels = 84;
- // The target margin to be applied to the navigation bar when the logo is hidden.
- const menuTopMargin = 70;
- // The max-height offset when the logo is completely visible.
- const menuHeightOffset_default = 162;
- // The max-height offset when the logo is completely hidden.
- const menuHeightOffset_fixed = 80;
- // The distance between the two max-height offset values above; used for intermediate values.
- const menuHeightOffset_diff = (menuHeightOffset_default - menuHeightOffset_fixed);
-
- // Media query handler.
- return function (mediaQuery) {
- // We only apply this logic to the "desktop" resolution (defined by a media query at the bottom).
- // This handler is executed when the result of the query evaluation changes, which means that
- // the page has moved between "desktop" and "mobile" states.
-
- // When entering the "desktop" state, we register scroll events and adjust elements on the page.
- // When entering the "mobile" state, we clean up any registered events and restore elements on the page
- // to their initial state.
-
- const $window = $(window);
- const $sidebar = $('.wy-side-scroll');
- const $search = $sidebar.children('.wy-side-nav-search');
- const $menu = $sidebar.children('.wy-menu-vertical');
- const $ethical = $sidebar.children('.ethical-rtd');
-
- // This padding is needed to correctly adjust the height of the scrollable area in the sidebar.
- // It has to have the same height as the ethical block, if there is one.
- let $menuPadding = $menu.children('.wy-menu-ethical-padding');
- if ($menuPadding.length == 0) {
- $menuPadding = $('
');
- $menu.append($menuPadding);
- }
-
- if (mediaQuery.matches) {
- // Entering the "desktop" state.
-
- // The main scroll event handler.
- // Executed as the page is scrolled and once immediately as the page enters this state.
- const handleMainScroll = (currentScroll) => {
- if (currentScroll >= scrollTopPixels) {
- // After the page is scrolled below the threshold, we fix everything in place.
- $search.css('margin-top', `-${scrollTopPixels}px`);
- $menu.css('margin-top', `${menuTopMargin}px`);
- $menu.css('max-height', `calc(100% - ${menuHeightOffset_fixed}px)`);
- } else {
- // Between the top of the page and the threshold we calculate intermediate values
- // to guarantee a smooth transition.
- $search.css('margin-top', `-${currentScroll}px`);
- $menu.css('margin-top', `${menuTopMargin + (scrollTopPixels - currentScroll)}px`);
-
- if (currentScroll > 0) {
- const scrolledPercent = (scrollTopPixels - currentScroll) / scrollTopPixels;
- const offsetValue = menuHeightOffset_fixed + menuHeightOffset_diff * scrolledPercent;
- $menu.css('max-height', `calc(100% - ${offsetValue}px)`);
- } else {
- $menu.css('max-height', `calc(100% - ${menuHeightOffset_default}px)`);
- }
- }
- };
-
- // The sidebar scroll event handler.
- // Executed as the sidebar is scrolled as well as after the main scroll. This is needed
- // because the main scroll can affect the scrollable area of the sidebar.
- const handleSidebarScroll = () => {
- const menuElement = $menu.get(0);
- const menuScrollTop = $menu.scrollTop();
- const menuScrollBottom = menuElement.scrollHeight - (menuScrollTop + menuElement.offsetHeight);
-
- // As the navigation is scrolled we add a shadow to the top bar hanging over it.
- if (menuScrollTop > 0) {
- $search.addClass('fixed-and-scrolled');
- } else {
- $search.removeClass('fixed-and-scrolled');
- }
-
- // Near the bottom we start moving the sidebar banner into view.
- if (menuScrollBottom < ethicalOffsetBottom) {
- $ethical.css('display', 'block');
- $ethical.css('margin-top', `-${ethicalOffsetBottom - menuScrollBottom}px`);
- } else {
- $ethical.css('display', 'none');
- $ethical.css('margin-top', '0px');
- }
- };
-
- $search.addClass('fixed');
- $ethical.addClass('fixed');
-
- // Adjust the inner height of navigation so that the banner can be overlaid there later.
- const ethicalOffsetBottom = $ethical.height() || 0;
- if (ethicalOffsetBottom) {
- $menuPadding.css('height', `${ethicalOffsetBottom}px`);
- } else {
- $menuPadding.css('height', `0px`);
- }
-
- $window.scroll(function () {
- handleMainScroll(window.scrollY);
- handleSidebarScroll();
- });
-
- $menu.scroll(function () {
- handleSidebarScroll();
- });
-
- handleMainScroll(window.scrollY);
- handleSidebarScroll();
- } else {
- // Entering the "mobile" state.
-
- $window.unbind('scroll');
- $menu.unbind('scroll');
-
- $search.removeClass('fixed');
- $ethical.removeClass('fixed');
-
- $search.css('margin-top', `0px`);
- $menu.css('margin-top', `0px`);
- $menu.css('max-height', 'initial');
- $menuPadding.css('height', `0px`);
- $ethical.css('margin-top', '0px');
- $ethical.css('display', 'block');
- }
- };
-})();
-
-// Subscribe to DOM changes in the sidebar container, because there is a
-// banner that gets added at a later point, that we might not catch otherwise.
-const registerSidebarObserver = (function () {
- return function (callback) {
- const sidebarContainer = document.querySelector('.wy-side-scroll');
-
- let sidebarEthical = null;
- const registerEthicalObserver = () => {
- if (sidebarEthical) {
- // Do it only once.
- return;
- }
-
- sidebarEthical = sidebarContainer.querySelector('.ethical-rtd');
- if (!sidebarEthical) {
- // Do it only after we have the element there.
- return;
- }
-
- // This observer watches over the ethical block in sidebar, and all of its subtree.
- const ethicalObserverConfig = {childList: true, subtree: true};
- const ethicalObserverCallback = (mutationsList, observer) => {
- for (let mutation of mutationsList) {
- if (mutation.type !== 'childList') {
- continue;
- }
-
- callback();
- }
- };
-
- const ethicalObserver = new MutationObserver(ethicalObserverCallback);
- ethicalObserver.observe(sidebarEthical, ethicalObserverConfig);
- };
- registerEthicalObserver();
-
- // This observer watches over direct children of the main sidebar container.
- const observerConfig = {childList: true};
- const observerCallback = (mutationsList, observer) => {
- for (let mutation of mutationsList) {
- if (mutation.type !== 'childList') {
- continue;
- }
-
- callback();
- registerEthicalObserver();
- }
- };
-
- const observer = new MutationObserver(observerCallback);
- observer.observe(sidebarContainer, observerConfig);
-
- // Default TOC tree has links that immediately navigate to the selected page. Our
- // theme adds an extra button to fold and unfold the tree without navigating away.
- // But that means that the buttons are added after the initial load, so we need to
- // improvise to detect clicks on these buttons.
- const scrollElement = document.querySelector('.wy-menu-vertical');
- const registerLinkHandler = (linkChildren) => {
- linkChildren.forEach(it => {
- if (it.nodeType === Node.ELEMENT_NODE && it.classList.contains('toctree-expand')) {
- it.addEventListener('click', () => {
- // Toggling a different item will close the currently opened one,
- // which may shift the clicked item out of the view. We correct for that.
- const menuItem = it.parentNode;
- const baseScrollOffset = scrollElement.scrollTop + scrollElement.offsetTop;
- const maxScrollOffset = baseScrollOffset + scrollElement.offsetHeight;
-
- if (menuItem.offsetTop < baseScrollOffset || menuItem.offsetTop > maxScrollOffset) {
- menuItem.scrollIntoView();
- }
-
- callback();
- });
- }
- });
- }
-
- const navigationSections = document.querySelectorAll('.wy-menu-vertical ul');
- navigationSections.forEach(it => {
- if (it.previousSibling == null || typeof it.previousSibling === 'undefined' || it.previousSibling.tagName != 'A') {
- return;
- }
-
- const navigationLink = it.previousSibling;
- registerLinkHandler(navigationLink.childNodes);
-
- const linkObserverConfig = {childList: true};
- const linkObserverCallback = (mutationsList, observer) => {
- for (let mutation of mutationsList) {
- registerLinkHandler(mutation.addedNodes);
- }
- };
-
- const linkObserver = new MutationObserver(linkObserverCallback);
- linkObserver.observe(navigationLink, linkObserverConfig);
- });
- };
-})();
-
-$(document).ready(() => {
- // Remove the search match highlights from the page, and adjust the URL in the
- // navigation history.
- const url = new URL(location.href);
- if (url.searchParams.has('highlight')) {
- Documentation.hideSearchWords();
- }
-
- window.addEventListener('keydown', function (event) {
- if (event.key === '/') {
- var searchField = document.querySelector('#rtd-search-form input[type=text]');
- if (document.activeElement !== searchField) {
- searchField.focus();
- searchField.select();
- event.preventDefault();
- }
- }
- });
-
- // Initialize handlers for page scrolling and our custom sidebar.
- const mediaQuery = window.matchMedia('only screen and (min-width: 769px)');
-
- registerOnScrollEvent(mediaQuery);
- mediaQuery.addListener(registerOnScrollEvent);
-
- registerSidebarObserver(() => {
- registerOnScrollEvent(mediaQuery);
- });
-
- // Add line-break suggestions to the sidebar navigation items in the class reference section.
- //
- // Some class reference pages have very long PascalCase names, such as
- // VisualShaderNodeCurveXYZTexture
- // Those create issues for our layout, as we can neither make them wrap with CSS without
- // breaking normal article titles, nor is it good to have them overflow their containers.
- // So we use a tag to insert mid-word suggestions for appropriate splits, so the browser
- // knows that it's okay to split it like
- // Visual Shader Node Curve XYZTexture
- // and add a new line at an opportune moment.
- const classReferenceLinks = document.querySelectorAll('.wy-menu-vertical > ul:last-of-type .reference.internal');
- for (const linkItem of classReferenceLinks) {
- let textNode = null;
- linkItem.childNodes.forEach(it => {
- if (it.nodeType === Node.TEXT_NODE) {
- // If this is a text node and if it needs to be updated, store a reference.
- let text = it.textContent;
- if (!(text.includes(" ") || text.length < 10)) {
- textNode = it;
- }
- }
- });
-
- if (textNode != null) {
- let text = textNode.textContent;
- // Add suggested line-breaks and replace the original text.
- // The regex looks for a lowercase letter followed by a number or an uppercase
- // letter. We avoid splitting at the last character in the name, though.
- text = text.replace(/([a-z])([A-Z0-9](?!$))/gm, '$1$2');
-
- linkItem.removeChild(textNode);
- linkItem.insertAdjacentHTML('beforeend', text);
- }
- }
-
- // Change indentation from spaces to tabs for codeblocks.
- const codeBlocks = document.querySelectorAll('.rst-content div[class^="highlight"] pre');
- for (const codeBlock of codeBlocks) {
- const classList = codeBlock.parentNode.parentNode.classList;
- if (!classList.contains('highlight-gdscript') && !classList.contains('highlight-cpp')) {
- // Only change indentation for GDScript and C++.
- continue;
- }
- let html = codeBlock.innerHTML.replace(/^()?( {4})/gm, '\t');
- let html_old = "";
- while (html != html_old) {
- html_old = html;
- html = html.replace(/\t( {4})/gm, '\t\t')
- }
- codeBlock.innerHTML = html;
- }
-
- // See `godot_is_latest` in conf.py
- const isLatest = document.querySelector('meta[name=doc_is_latest]').content.toLowerCase() === 'true';
- if (isLatest) {
- // Add a compatibility notice using JavaScript so it doesn't end up in the
- // automatically generated `meta description` tag.
-
- const baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
- // These lines only work as expected in the production environment, can't test this locally.
- const fallbackUrl = baseUrl.replace('/latest/', '/stable/');
- const homeUrl = baseUrl.split('/latest/')[0] + '/stable/';
- const searchUrl = homeUrl + 'search.html?q=';
-
- const noticeLink = document.querySelector('.latest-notice-link');
-
- // Insert a placeholder to display as we're making a request.
- noticeLink.innerHTML = `
- Checking the stable version
- of the documentation...
- `;
+document.addEventListener("DOMContentLoaded", () => {
+ const menuHeaders = document.querySelectorAll('.wy-menu-vertical .caption');
+ let hasCurrent = false;
- // Make a HEAD request to the possible stable URL to check if the page exists.
- fetch(fallbackUrl, {method: 'HEAD'})
- .then((res) => {
- // We only check the HTTP status, which should tell us if the link is valid or not.
- if (res.status === 200) {
- noticeLink.innerHTML = `
- See the stable version
- of this documentation page instead.
- `;
- } else {
- // Err, just to fallthrough to catch.
- throw Error('Bad request');
- }
- })
- .catch((err) => {
- let message = `
- This page does not exist in the stable version
- of the documentation.
- `;
+ menuHeaders.forEach(header => {
+ const connectedMenu = header.nextElementSibling; // The dropdown menu (e.g., `ul`)
- // Also suggest a search query using the page's title. It should work with translations as well.
- // Note that we can't use the title tag as it has a permanent suffix. OG title doesn't, though.
- const titleMeta = document.querySelector('meta[property="og:title"]');
- if (typeof titleMeta !== 'undefined') {
- const pageTitle = titleMeta.getAttribute('content');
- message += `
- You can try searching for "${pageTitle}" instead.
- `;
- }
+ // Toggle dropdown visibility on click
+ header.addEventListener('click', () => {
+ const isActive = connectedMenu.classList.contains('active');
- noticeLink.innerHTML = message;
+ // Close all dropdowns
+ menuHeaders.forEach(otherHeader => {
+ const otherMenu = otherHeader.nextElementSibling;
+ otherMenu.classList.remove('active');
+ otherHeader.classList.remove('active');
});
- }
- // Load instant.page to prefetch pages upon hovering. This makes navigation feel
- // snappier. The script is dynamically appended as Read the Docs doesn't have
- // a way to add scripts with a "module" attribute.
- const instantPageScript = document.createElement('script');
- instantPageScript.toggleAttribute('module');
- /*! instant.page v5.1.0 - (C) 2019-2020 Alexandre Dieulot - https://instant.page/license */
- instantPageScript.innerText = 'let t,e;const n=new Set,o=document.createElement("link"),i=o.relList&&o.relList.supports&&o.relList.supports("prefetch")&&window.IntersectionObserver&&"isIntersecting"in IntersectionObserverEntry.prototype,s="instantAllowQueryString"in document.body.dataset,a="instantAllowExternalLinks"in document.body.dataset,r="instantWhitelist"in document.body.dataset,c="instantMousedownShortcut"in document.body.dataset,d=1111;let l=65,u=!1,f=!1,m=!1;if("instantIntensity"in document.body.dataset){const t=document.body.dataset.instantIntensity;if("mousedown"==t.substr(0,"mousedown".length))u=!0,"mousedown-only"==t&&(f=!0);else if("viewport"==t.substr(0,"viewport".length))navigator.connection&&(navigator.connection.saveData||navigator.connection.effectiveType&&navigator.connection.effectiveType.includes("2g"))||("viewport"==t?document.documentElement.clientWidth*document.documentElement.clientHeight<45e4&&(m=!0):"viewport-all"==t&&(m=!0));else{const e=parseInt(t);isNaN(e)||(l=e)}}if(i){const n={capture:!0,passive:!0};if(f||document.addEventListener("touchstart",function(t){e=performance.now();const n=t.target.closest("a");if(!h(n))return;v(n.href)},n),u?c||document.addEventListener("mousedown",function(t){const e=t.target.closest("a");if(!h(e))return;v(e.href)},n):document.addEventListener("mouseover",function(n){if(performance.now()-e{v(o.href),t=void 0},l)},n),c&&document.addEventListener("mousedown",function(t){if(performance.now()-e1||t.metaKey||t.ctrlKey)return;if(!n)return;n.addEventListener("click",function(t){1337!=t.detail&&t.preventDefault()},{capture:!0,passive:!1,once:!0});const o=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1,detail:1337});n.dispatchEvent(o)},n),m){let t;(t=window.requestIdleCallback?t=>{requestIdleCallback(t,{timeout:1500})}:t=>{t()})(()=>{const t=new IntersectionObserver(e=>{e.forEach(e=>{if(e.isIntersecting){const n=e.target;t.unobserve(n),v(n.href)}})});document.querySelectorAll("a").forEach(e=>{h(e)&&t.observe(e)})})}}function p(e){e.relatedTarget&&e.target.closest("a")==e.relatedTarget.closest("a")||t&&(clearTimeout(t),t=void 0)}function h(t){if(t&&t.href&&(!r||"instant"in t.dataset)&&(a||t.origin==location.origin||"instant"in t.dataset)&&["http:","https:"].includes(t.protocol)&&("http:"!=t.protocol||"https:"!=location.protocol)&&(s||!t.search||"instant"in t.dataset)&&!(t.hash&&t.pathname+t.search==location.pathname+location.search||"noInstant"in t.dataset))return!0}function v(t){if(n.has(t))return;const e=document.createElement("link");e.rel="prefetch",e.href=t,document.head.appendChild(e),n.add(t)}';
- document.head.appendChild(instantPageScript);
-
- // Make sections in the sidebar togglable.
- let hasCurrent = false;
- let menuHeaders = document.querySelectorAll('.wy-menu-vertical .caption[role=heading]');
- menuHeaders.forEach(it => {
- let connectedMenu = it.nextElementSibling;
-
- // Enable toggling.
- it.addEventListener('click', () => {
- if (connectedMenu.classList.contains('active')) {
- connectedMenu.classList.remove('active');
- it.classList.remove('active');
- } else {
+ // Open the clicked dropdown if it was closed
+ if (!isActive) {
connectedMenu.classList.add('active');
- it.classList.add('active');
+ header.classList.add('active');
}
+ });
- // Hide other sections.
- menuHeaders.forEach(ot => {
- if (ot !== it && ot.classList.contains('active')) {
- ot.nextElementSibling.classList.remove('active');
- ot.classList.remove('active');
- }
- });
-
- registerOnScrollEvent(mediaQuery);
- }, true);
-
- // Set the default state, expand our current section.
- if (connectedMenu.classList.contains('current')) {
+ // Automatically expand the dropdown if it contains the "current" page
+ if (connectedMenu.querySelector('.current')) {
connectedMenu.classList.add('active');
- it.classList.add('active');
-
+ header.classList.add('active');
hasCurrent = true;
}
});
- // Unfold the first (general information) section on the home page.
+ // If no dropdown contains the "current" page, expand the first section by default
if (!hasCurrent && menuHeaders.length > 0) {
menuHeaders[0].classList.add('active');
menuHeaders[0].nextElementSibling.classList.add('active');
-
- registerOnScrollEvent(mediaQuery);
}
});
-
-// Override the default implementation from doctools.js to avoid this behavior.
-Documentation.highlightSearchWords = function () {
- // Nope.
-}
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index b46ae46..d62754d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,15 +1,15 @@
import os
import subprocess
-breathe_projects = {'KrakenEngine': 'xml'}
-breathe_default_project = 'KrakenEngine'
+breathe_projects = {"KrakenEngine": "xml"}
+breathe_default_project = "KrakenEngine"
needs_sphinx = "7.1"
extensions = [
- 'breathe',
- 'sphinx.ext.autosectionlabel',
- 'notfound.extension',
+ "breathe",
+ "sphinx.ext.autosectionlabel",
+ "notfound.extension",
]
notfound_context = {
@@ -35,22 +35,22 @@
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if on_rtd:
- subprocess.call('doxygen', shell=True)
+ subprocess.call("doxygen", shell=True)
else:
notfound_urls_prefix = ''
templates_path = ["_templates"]
-source_suffix = '.rst'
+source_suffix = ".rst"
source_encoding = "utf-8-sig"
-master_doc = 'index'
+master_doc = "index"
-project = 'Kraken Engine'
-copyright = '2024, Derrick Martinez'
-author = 'Derrick Martinez'
+project = "Kraken Engine"
+copyright = "2024, Derrick Martinez"
+author = "Derrick Martinez"
-version = os.getenv("READTHEDOCS_VERSION", "0.0.3")
+version = os.getenv("READTHEDOCS_VERSION", "0.0.6")
release = version
exclude_patterns = ["_build"]
@@ -66,7 +66,6 @@
html_theme_options = {
"logo_only": True,
"collapse_navigation": False,
- "display_version": False,
}
html_title = f"Kraken Engine ({version}) documentation in English"
@@ -75,8 +74,8 @@
"display_github": True, # Integrate GitHub
"github_user": "durkisneer1", # Username
"github_repo": "Kraken-Engine", # Repo name
- "github_version": "0.0.3", # Version
- "conf_py_path": "/", # Path in the checkout to the docs root
+ "github_version": "main", # Version
+ "conf_py_path": "/docs/", # Path in the checkout to the docs root
"kraken_docs_title": html_title,
"kraken_docs_basepath": "https://kraken-engine.readthedocs.io/",
"kraken_docs_suffix": ".html",
@@ -84,24 +83,16 @@
"kraken_canonical_version": "stable",
# Set this to `True` when in the `latest` branch to clearly indicate to the reader
# that they are not reading the `stable` documentation.
- "kraken_is_latest": False,
- "kraken_version": "0.0.3",
+ "kraken_is_latest": True,
+ "kraken_version": "0.0.6",
# Enables a banner that displays the up-to-date status of each article.
"kraken_show_article_status": True,
}
html_logo = "_static/kraken-engine-banner.png"
-html_static_path = ['_static']
-
-html_css_files = [
- 'css/algolia.css',
- 'https://cdn.jsdelivr.net/npm/@docsearch/css@3',
- "css/custom.css",
-]
-
-html_js_files = [
- "js/custom.js",
-]
+html_static_path = ["_static"]
+html_css_files = ["css/custom.css"]
+html_js_files = ["js/custom.js"]
file_insertion_enabled = False
@@ -110,4 +101,4 @@
gettext_compact = False
-epub_tocscope = 'includehidden'
+epub_tocscope = "includehidden"
diff --git a/docs/getting_started/create_window.rst b/docs/getting_started/create_window.rst
index 36b3e83..2fc903f 100644
--- a/docs/getting_started/create_window.rst
+++ b/docs/getting_started/create_window.rst
@@ -2,6 +2,7 @@ Creating a Window
=================
After following the :doc:`installation` guide, you are ready for your first Kraken Engine program.
+The following code creates a window and keeps it open until the user closes it.
.. code-block:: c++
:linenos:
@@ -11,21 +12,17 @@ After following the :doc:`installation` guide, you are ready for your first Krak
int main()
{
kn::window::init({800, 600});
- kn::time::Clock clock;
- bool done = false;
- while (!done)
+ kn::Event event;
+ while (kn::window::isOpen())
{
- clock.tick();
+ kn::window::pollEvent(event);
+ if (event.type == kn::QUIT)
+ kn::window::close();
- for (const auto &event : kn::window::getEvents())
- if (event.type == kn::QUIT)
- done = true;
-
- kn::window::clear();
kn::window::flip();
}
-
kn::window::quit();
+
return EXIT_SUCCESS;
}
diff --git a/docs/index.rst b/docs/index.rst
index 20b0cd2..d4909c8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -30,6 +30,7 @@ We look forward to seeing the incredible games you create with the Kraken Engine
.. toctree::
:hidden:
:maxdepth: 1
+ :caption: Getting Started
getting_started/installation
getting_started/create_window
@@ -37,17 +38,32 @@ We look forward to seeing the incredible games you create with the Kraken Engine
.. toctree::
:hidden:
:maxdepth: 1
+ :caption: Manual
tutorials/index
.. toctree::
:hidden:
:maxdepth: 1
+ :caption: Contributing
contributing/how_to_contribute
.. toctree::
:hidden:
:maxdepth: 1
-
- reference/index
\ No newline at end of file
+ :caption: API Reference
+
+ reference/animation_controller
+ reference/font
+ reference/rect
+ reference/sound
+ reference/texture
+ reference/tile_map
+ reference/constants
+ reference/draw
+ reference/input
+ reference/math
+ reference/music
+ reference/time
+ reference/window
\ No newline at end of file
diff --git a/docs/reference/animation_controller.rst b/docs/reference/animation_controller.rst
index 6049823..b254992 100644
--- a/docs/reference/animation_controller.rst
+++ b/docs/reference/animation_controller.rst
@@ -11,7 +11,7 @@ What the AnimationController class does **NOT** do is provide a draw function.
This design decision is to give users the flexibility to draw the current frame in a desired position and size.
Usage
--------------
+-----
.. code-block:: cpp
@@ -33,5 +33,8 @@ Usage
// Draw the current frame texture at position (50, 50) and size (16, 16).
kn::window::blit(*frame.tex, {50, 50, 16, 16}, frame.rect);
+Members
+-------
+
.. doxygenclass:: kn::AnimationController
:members:
diff --git a/docs/reference/font.rst b/docs/reference/font.rst
index 3ad2e13..b21ddf2 100644
--- a/docs/reference/font.rst
+++ b/docs/reference/font.rst
@@ -20,5 +20,8 @@ Usage
// Draw the text texture at position (50, 50).
kn::window::blit(text, {50, 50});
+Members
+-------
+
.. doxygenclass:: kn::Font
:members:
\ No newline at end of file
diff --git a/docs/reference/index.rst b/docs/reference/index.rst
deleted file mode 100644
index bb07367..0000000
--- a/docs/reference/index.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-=============
-API Reference
-=============
-
-.. toctree::
- :maxdepth: 1
-
- animation_controller.rst
- font.rst
- rect.rst
- sound.rst
- texture.rst
- tile_map.rst
- constants.rst
- draw.rst
- input.rst
- math.rst
- music.rst
- time.rst
- window.rst
\ No newline at end of file
diff --git a/docs/reference/input.rst b/docs/reference/input.rst
index c42560a..9a0d3d2 100644
--- a/docs/reference/input.rst
+++ b/docs/reference/input.rst
@@ -31,6 +31,9 @@ Usage
kn::math::Vec2 inputDir = kn::input::getVector(left, right, up, down);
+Functions
+---------
+
.. doxygenfunction:: kn::input::getMousePos
.. doxygenfunction:: kn::input::isMouseButtonPressed
diff --git a/docs/reference/music.rst b/docs/reference/music.rst
index c8ab7e0..3f7ed3e 100644
--- a/docs/reference/music.rst
+++ b/docs/reference/music.rst
@@ -28,6 +28,9 @@ Usage
// Fade out the music over 2 seconds.
kn::music::fadeOut(2000);
+Functions
+---------
+
.. doxygenfunction:: kn::music::load
.. doxygenfunction:: kn::music::unload
diff --git a/docs/reference/sound.rst b/docs/reference/sound.rst
index f57ef6f..306b7db 100644
--- a/docs/reference/sound.rst
+++ b/docs/reference/sound.rst
@@ -25,5 +25,8 @@ Usage
// Play the sound 3 times after it fades in over 2 seconds.
sound.play(2, -1, 2000);
+Members
+-------
+
.. doxygenclass:: kn::Sound
:members:
diff --git a/docs/reference/texture.rst b/docs/reference/texture.rst
index 7b207fb..95a8904 100644
--- a/docs/reference/texture.rst
+++ b/docs/reference/texture.rst
@@ -29,6 +29,8 @@ Usage
kn::window::blit(imageTexture, {50, 50});
kn::window::blit(colorTexture, {100, 100});
+Members
+-------
.. doxygenclass:: kn::Texture
:members:
\ No newline at end of file
diff --git a/docs/reference/tile_map.rst b/docs/reference/tile_map.rst
index bac1474..88d1791 100644
--- a/docs/reference/tile_map.rst
+++ b/docs/reference/tile_map.rst
@@ -41,6 +41,9 @@ Usage
tileMap.drawMap();
tileMap.drawLayer("walls");
+Members
+-------
+
.. doxygenstruct:: kn::Tile
:members:
:undoc-members:
diff --git a/docs/reference/time.rst b/docs/reference/time.rst
index fe0ecc1..b695103 100644
--- a/docs/reference/time.rst
+++ b/docs/reference/time.rst
@@ -21,7 +21,13 @@ Usage
// Get the time since Kraken was initialized.
double elapsedTime = kn::time::getTicks();
+Members
+-------
+
.. doxygenclass:: kn::time::Clock
:members:
+Functions
+---------
+
.. doxygenfunction:: kn::time::getTicks
diff --git a/example/main.cpp b/example/main.cpp
index 31fd963..62252bd 100644
--- a/example/main.cpp
+++ b/example/main.cpp
@@ -12,15 +12,18 @@ int main()
Player player(tileMap);
- bool done = false;
- while (!done)
+ kn::Event event;
+ while (kn::window::isOpen())
{
const double dt = clock.tick();
- for (const auto& event : kn::window::getEvents())
- if (event.type == kn::QUIT ||
- (event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE))
- done = true;
+ kn::window::pollEvent(event);
+ if (event.type == kn::QUIT ||
+ (event.type == kn::KEYDOWN && event.key.keysym.sym == kn::K_ESCAPE))
+ kn::window::close();
+ if (event.type == kn::MOUSEMOTION)
+ if (event.type == kn::MOUSEBUTTONDOWN)
+ std::cout << "yes\n";
kn::window::clear({21, 18, 37});
diff --git a/include/Window.hpp b/include/Window.hpp
index f86fc87..d23a2c8 100644
--- a/include/Window.hpp
+++ b/include/Window.hpp
@@ -29,6 +29,18 @@ namespace window
*/
void init(const math::Vec2& resolution, const std::string& title = "Kraken Window", int scale = 1);
+/**
+ * @brief Get whether the window is open.
+ *
+ * @return Whether the window is open.
+ */
+bool isOpen();
+
+/**
+ * @brief Close the window.
+ */
+void close();
+
/**
* @brief Clear the screen.
*
@@ -66,11 +78,11 @@ void blit(const Texture& texture, const math::Vec2& position = {});
SDL_Renderer* getRenderer();
/**
- * @brief Get user events.
+ * @brief Populate an event with the next window events.
*
- * @return The user events.
+ * @param event The event to poll.
*/
-const std::vector& getEvents();
+void pollEvent(Event& event);
/**
* @brief Get whether the window is fullscreen or not.
diff --git a/src/window.cpp b/src/window.cpp
index 0c7415a..c4dd13f 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -10,8 +10,7 @@ namespace kn::window
{
static SDL_Renderer* _renderer;
static SDL_Window* _window;
-static Event _event;
-static std::vector _events;
+static bool _isOpen;
void init(const math::Vec2& resolution, const std::string& title, const int scale)
{
@@ -57,8 +56,14 @@ void init(const math::Vec2& resolution, const std::string& title, const int scal
setTitle(title);
setIcon("../example/assets/kraken_engine_window_icon.png");
+
+ _isOpen = true;
}
+bool isOpen() { return _isOpen; }
+
+void close() { _isOpen = false; }
+
void quit()
{
if (_renderer)
@@ -73,16 +78,12 @@ void quit()
SDL_Quit();
}
-const std::vector& getEvents()
+void pollEvent(Event& event)
{
if (!_window)
WARN("Cannot get events before creating the window")
- _events.clear();
- while (SDL_PollEvent(&_event))
- _events.push_back(_event);
-
- return _events;
+ SDL_PollEvent(&event);
}
void clear(const Color color)