From acab7a314db54f50ebfb1201279eb16c47460f2b Mon Sep 17 00:00:00 2001 From: durk Date: Wed, 4 Dec 2024 15:54:32 -0600 Subject: [PATCH] new way to handle window and events documentation category dropdowns now work --- docs/_static/css/algolia.css | 6 - docs/_static/css/custom.css | 5 - docs/_static/js/custom.js | 434 ++---------------------- docs/conf.py | 49 ++- docs/getting_started/create_window.rst | 17 +- docs/index.rst | 20 +- docs/reference/animation_controller.rst | 5 +- docs/reference/font.rst | 3 + docs/reference/index.rst | 20 -- docs/reference/input.rst | 3 + docs/reference/music.rst | 3 + docs/reference/sound.rst | 3 + docs/reference/texture.rst | 2 + docs/reference/tile_map.rst | 3 + docs/reference/time.rst | 6 + example/main.cpp | 15 +- include/Window.hpp | 18 +- src/window.cpp | 17 +- 18 files changed, 126 insertions(+), 503 deletions(-) delete mode 100644 docs/_static/css/algolia.css delete mode 100644 docs/reference/index.rst 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)