├── 404.html ├── Docs ├── ReleaseNotes │ ├── cave-11-vs-12-importing.png │ ├── cave-11-vs-12-vs-ue55.png │ ├── cave-bible-banner.png │ ├── image-1.png │ ├── image-2.png │ ├── image-3.png │ ├── image-4.png │ ├── image-5.png │ ├── image-6.png │ ├── image.png │ ├── v097 │ │ └── index.html │ ├── v0972 │ │ └── index.html │ ├── v098 │ │ └── index.html │ ├── v099 │ │ └── index.html │ └── v120 │ │ └── index.html ├── eula │ └── index.html ├── faq │ └── index.html └── roadmap │ └── index.html ├── PythonAPI ├── Assets │ ├── audio │ │ └── index.html │ ├── materials │ │ └── index.html │ └── meshes │ │ └── index.html ├── Components │ ├── gameplay │ │ └── index.html │ ├── graphics │ │ └── index.html │ ├── interface │ │ └── index.html │ ├── physics │ │ └── index.html │ └── transform │ │ └── index.html ├── Core │ ├── component │ │ └── index.html │ ├── entity │ │ └── index.html │ └── scene │ │ └── index.html ├── EditorAPI │ ├── tooling │ │ └── index.html │ └── uiModule │ │ └── index.html ├── Events │ ├── events │ │ └── index.html │ └── keycodes │ │ └── index.html ├── cave1 │ └── index.html ├── engineMisc │ └── index.html ├── engineUtils │ └── index.html ├── introduction │ └── index.html └── math │ └── index.html ├── Showcase └── games │ └── index.html ├── css ├── base.css ├── bootstrap.min.css ├── bootstrap.min.css.map ├── brands.min.css ├── fontawesome.min.css ├── solid.min.css └── v4-font-face.min.css ├── engine.pyi ├── img ├── favicon.ico └── grid.png ├── index.html ├── js ├── base.js ├── bootstrap.bundle.min.js ├── bootstrap.bundle.min.js.map └── darkmode.js ├── search ├── lunr.js ├── main.js ├── search_index.json └── worker.js ├── sitemap.xml ├── sitemap.xml.gz └── webfonts ├── fa-brands-400.ttf ├── fa-brands-400.woff2 ├── fa-regular-400.ttf ├── fa-regular-400.woff2 ├── fa-solid-900.ttf ├── fa-solid-900.woff2 ├── fa-v4compatibility.ttf └── fa-v4compatibility.woff2 /404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 242 | 243 |
244 |
245 | 246 |
247 |
248 |

404

249 |

Page not found

250 |
251 |
252 | 253 | 254 |
255 |
256 | 257 | 261 | 262 | 266 | 267 | 268 | 269 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /Docs/ReleaseNotes/cave-11-vs-12-importing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/cave-11-vs-12-importing.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/cave-11-vs-12-vs-ue55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/cave-11-vs-12-vs-ue55.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/cave-bible-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/cave-bible-banner.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-1.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-2.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-3.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-4.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-5.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image-6.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/Docs/ReleaseNotes/image.png -------------------------------------------------------------------------------- /Docs/ReleaseNotes/v098/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Cave 0.9.8 - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
277 |
278 | 279 |

Cave Engine 0.9.8 Release Notes!

280 |

Welcome to the biggest Cave release yet!

281 |

In fact, this release is so big that I've started to write its release notes a while ago (Check the Release Notes for v0.9.7.2!) and was not able to put even half of it in the document.

282 |

And since this release note is pretty much what's delaying the engine from actually being released, I'll leave it as a "TODO" here for now. But feel free to join our discord server to discover the rest of the new features! :)

283 |

Our Discord Servers

284 |
288 |
289 |
290 | 291 | 295 | 296 | 300 | 301 | 302 | 303 | 363 | 364 | 365 | 366 | -------------------------------------------------------------------------------- /PythonAPI/Assets/audio/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Audio Playing - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
282 |
283 | 284 |

Audio Playing

285 |

You can play any sound you want anytime by calling the cave.playSound function. You'll need to pass the asset name for the sound (exactly how it is written in the asset browser) and the optional parameters:

286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
ParameterDescription
volumeHow loud or quiet the sound will be. 0 means muted, 1 means max.
fadeInIn seconds, if greated than zero, it will slowly fade in the sound by the amount of time you pass.
loopHow many times you want the sound to be played. -1 means that it will play forever, zero means that it will play once and 1 (or more) means that it will play and repeat by 1 (or the number you pass).
308 |

This function returns an AudioTrackInstance that allows you to later change those values, pause/resume the sound and more. Reference code:

309 |
cave.playSound(name: str, volume=1.0, fadeIn=0.0, loop=0) -> AudioTrackInstance
310 | 
311 |
312 |

The Audio Handler

313 |

As explained above, by calling cave.playSound, the function will return AudioTrackInstance. Here is everything you need to know about it:

314 |

cave.AudioTrackInstance

315 |

Here is an example of the AudioTrackInstance in action. The following component only plays the sound if the scene is NOT paused:

316 |
class AudioExample(cave.Component):
317 |     def start(self, scene):
318 |         self.handler = cave.playAudio("MyCoolSound.ogg", 1.0)
319 | 
320 |     def update(self):
321 |         if self.handler.isPaused():
322 |             self.handler.resume()
323 | 
324 |     def pausedUpdate(self):
325 |         if self.handler.isPlaying():
326 |             self.handler.pause()
327 | 
328 |
Variables
329 |

You can use this variable to adjust the sound volume. Keep in mind that it must be between 0 and 1.

330 |
volume : float
331 | 
332 |
Methods
333 |

Here is the basic operations to work with the sound (pause, resume and stop):

334 |
pause()
335 | resume()
336 | 
337 | # If you pass a fadeout (in seconds), if will slowly fade out the audio until it stops.
338 | stop(fadeOut=0.0)
339 | 
340 |

You can also use the handler to check certain things and status of it:

341 |
# Returns true if the track is being played or is paused. False if not:
342 | isActive() -> bool
343 | 
344 | isPlaying() -> bool
345 | isPaused()  -> bool
346 | isFadingIn()  -> bool
347 | isFadingOut() -> bool
348 | 
349 | # Returns the channel that this audio is being played at:
350 | getChannel() -> int
351 | 
352 |

3D Sounds:

353 |

Cave Engine supports 3D sounds, but you'll need to manually call this method every frame in order to update it:

354 |
calculate3D(audioPos: Vector3, maxDistance=100.0)
355 | 
356 |
357 |
358 | 359 | 363 | 364 | 368 | 369 | 370 | 371 | 431 | 432 | 433 | 434 | -------------------------------------------------------------------------------- /PythonAPI/Assets/materials/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Material Manipulation - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
290 |
291 | 292 |

Material Related Assets

293 |

In order to properly manipulate materials and colors in Cave, you'll need to acknowledge two main classes: ColorSampler and Material. Check them below.

294 |

Be aware that right now the engine does not support custom material shaders or pipelines, but it will provide you some basic functionalities such as changing colors and textures in realtime.

295 |
296 |

How to get a Material Instance?

297 |

The way you'll tipically get a Material class instance is by retrieving them from a MeshComponent, do NOT try to create your own instance from scratch, it will not work. Here is an example of how it's done:

298 |
# Getting the mesh component:
299 | meshComponent = self.entity.get("Mesh")
300 | 
301 | # Getting the material:
302 | material = meshComponent.getMaterial()
303 | 
304 | # If you want to change the material settings for a specific Entity, 
305 | # you can duplicate it and reassign to the Component:
306 | materialCopy = material.getCopy()
307 | meshComponent.setMaterial(materialCopy)
308 | 
309 | # Now you'll be able to do local changes to the *materialCopy*:
310 | materialCopy.albedo.set(1,0,0,1)
311 | 
312 |
313 |

Documentation

314 |

Here is the full documentation:

315 |

cave.ColorSampler

316 |

You probably have noticed that when it comes to Material colors, Cave Engine allows you most of the times to choose if you want to use a Texture (an image) or a raw Color (with reg, green, blue and alpha values). To archieve that, Cave uses what we call ColorSampler. You'll find ways to change its color below.

317 |
Methods
318 |
# Returns true if the color sampler has a texture.
319 | hasTexture() -> bool
320 | 
321 | # Will return the color sampler's color
322 | getColor() -> Vector4
323 | # Will return the color sampler's texture name (if there is a texture)
324 | getTexture() -> string
325 | 
326 |

In order to change the ColorSampler values, you can use one of those two setters, depending if you want to set it to a color or a texture.

327 |
# Use this one if you want to set it to a raw color:
328 | set(r: float, g: float, b: float, a=1.0)
329 | 
330 | # Use this one if you want to set it to a texture:
331 | set(textureName: str)
332 | 
333 |

cave.Material

334 |
Variables
335 |

All the following variables returns ColorSampler class instances. Check the documentation above for more details on how to handle them.

336 |
albedo:     ColorSampler
337 | roughness:  ColorSampler
338 | metallic:   ColorSampler
339 | normal:     ColorSampler
340 | emission:   ColorSampler
341 | 
342 |
Methods
343 |

If you need to duplicate a material (in order to do local changes to a specific Entity, for example), this is what you're looking for. It will duplicate the material and add it to the game data!

344 |
getCopy() -> cave.Material
345 | 
346 |
347 |
348 | 349 | 353 | 354 | 358 | 359 | 360 | 361 | 421 | 422 | 423 | 424 | -------------------------------------------------------------------------------- /PythonAPI/Components/interface/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Game UI - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
277 |
278 | 279 |

Game UI Components

280 |

As you may know, Cave Engine allows you to create custom in game UIs by using some Builtin Components. Here you'll find their available Python APIs.

281 |

cave.UIElementComponent

282 |
Variables
283 |

If the Element have a Font, you can type texts in it do be displayed in your game. For this, use the text variable:

284 |
text : str
285 | 
286 |

In order to position and scale your UI element, you can use those variables:

287 |
position : cave.UIVector
288 | scale    : cave.UIVector
289 | 
290 |

_ Note: Read the cave.UIVector's Documentation in the Math section of this API._

291 |

You can change the component's color by adjusting one of those variables:

292 |
quadAlpha : float
293 | quadColor : cave.Vector
294 | 
295 |
Methods
296 |

To see if the user is hovering your UI element, you can use thid method:

297 |
isHovered() -> bool
298 | 
299 |
300 |
301 | 302 | 306 | 307 | 311 | 312 | 313 | 314 | 374 | 375 | 376 | 377 | -------------------------------------------------------------------------------- /PythonAPI/EditorAPI/tooling/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Writting your own Tools - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
281 |
282 | 283 |

Writting your own Tools

284 |

In the Cave Engine you can write your own tools using python. They can be as simple as just executing a text to do something for you or more complex and well made tools, with a proper interface that contains buttons, sliders and whatever you want in a Tab format, that you can dock to the Editor's ui.

285 |

To start writting your tools, create a new Python Script in the asset browser, open it in the text editor (double click) and delete the current startup code.

286 |

Run your first Tool

287 |

Let's start with a simple tool that just sets some Sun light settings:

288 |
import cave
289 | 
290 | # You can write the code you want to using the cave API:
291 | scene = cave.getCurrentScene()
292 | sun = scene.getSun()
293 | 
294 | sun.hour = 6.15
295 | sun.intensity = 5.0
296 | sun.color = cave.Vector3(1.0, 0.8, 0.8)
297 | 
298 |

In order to run this code, simply go to "Editor Tools.." and then "Run Script":

299 |

300 |

It will run and change the sun settings, as expected. Note that you can use print(...) here to debug your stuff as well.

301 |

Have fun!

302 |

Create a Tab and Interface for your Tool

303 |

Now that you already know how to run simple scripts like that, it's time to understand how to do some a bit more advanced ones. So let's start talking about a tool with its own Tab docked in the editor, with a proper interface with buttons, sliders and so on. Here is a screenshot showing that in action. The code in the left generated the tab highlighted in red:

304 |

305 |

Here is a simple code that produces a similar result and can be used as a starting point for your own tools:

306 |
import cave
307 | import caveui as ui
308 | 
309 | class Example(ui.DebugTab):
310 |     def __init__(self):
311 |         super().__init__()
312 |         self.counter = 0
313 | 
314 |     def draw(self):
315 |         ui.text("Hello, world!")
316 |         ui.separator()
317 |         self.counter = ui.prop("Counter", self.counter)
318 |         if ui.button("Increase counter (+1)"):
319 |             self.counter += 1
320 | 
321 |

In order to run that and register the Tab to the ui, go to the "Editor Tools..." option and open the "Register Tab..." sub menu. It will automatically identify all the classes in the code that inherits from the base class caveui.DebugTab and show there. Simply click in the one you want to in order to register it.

322 |
323 |
324 | 325 | 329 | 330 | 334 | 335 | 336 | 337 | 397 | 398 | 399 | 400 | -------------------------------------------------------------------------------- /PythonAPI/Events/events/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Handling Events - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
277 |
278 | 279 |

Handling Events

280 |

In order to handle events in Cave (to see if the user pressed a keyboard or mouse key), you'll need to use the cave.Events class. Note that you cannot instantiace your own Events class, instead of this, you can get the engine's events class instance by calling this function:

281 |
events = cave.getEvents()
282 | 
283 |

cave.Events

284 |

Here is an example of the cave Events system in action:

285 |
events = cave.getEvents()
286 | 
287 | if events.pressed(cave.event.KEY_W):
288 |     print("The user pressed the key W!")
289 | 
290 | # You can also use the event names (as strings):
291 | if events.pressed("S"):
292 |     print("The user pressed the key S!")
293 | 
294 | # Mouse events works the same way:
295 | if events.released(cave.event.MOUSE_LEFT):
296 |     print("The user released the left mouse button!")
297 | 
298 |

Note: Again, do not instantiate a new instance of this class, you should always use the one provided by the cave.getEvents() function.

299 |
Methods
300 |
pressed(event : str) -> bool
301 | pressed(event : cave.event) -> bool
302 | 
303 |

Returns True if the user just pressed the event key or False if not.

304 |
active(event : str) -> bool
305 | active(event : cave.event) -> bool
306 | 
307 |

Always returns True while the user is pressing the event key or False if not.

308 |
released(event : str) -> bool
309 | released(event : cave.event) -> bool
310 | 
311 |

Returns True if the user just released the event key or False if not.

312 |
313 |

The following methods are related to mouse specific behaviours:

314 |
setRelativeMouse(value: bool)
315 | 
316 |

When enabled, the mouse will be invisible and the mouse motion will be computed (and available at GetMouseMotion()), but not applied to the mouse cursor.

317 |

If enabled, then if you want to know how much the user moved the mouse (useful to make a mouselook, for example), use the getMouseMotion function. Reference:

318 |
getMouseMotion() -> Vector2
319 | 
320 |
321 |
322 | 323 | 327 | 328 | 332 | 333 | 334 | 335 | 395 | 396 | 397 | 398 | -------------------------------------------------------------------------------- /PythonAPI/cave1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Cave Engine 1.x - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
273 |
274 | 275 |

Cave Engine 1.x - Python API

276 |

Please notice that this website only contains the old 0.9.x API, so if you're using the latest Cave Engine version (1.x), it may be outdated. You can still browse the old API in this website and learn from it if you want, but it's not recommended to take it for granted.

277 |

The Python API for Cave 1.x now comes with the engine itself, including stubs for your reference and intellisense.

278 |

If you have any questions, please contact Uniday Studio.

279 |
280 |
281 | 282 | 286 | 287 | 291 | 292 | 293 | 294 | 354 | 355 | 356 | 357 | -------------------------------------------------------------------------------- /PythonAPI/introduction/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Introduction - Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
285 |
286 | 287 |

Welcome to Cave Engine's Python API!

288 |

(Note: This API is up to date with Cave Engine v0.9.8 - PRO)

289 |

290 |

Welcome to the official Cave Engine API, written to give you a good overview of how python scripting works in Cave and also serve as a Reference for you to write your own custom code.

291 |

It was designed with readability in mind, so it's strongly recommended that you to take some time and read thought the entire API to better understand everything. It is full of code samples, tips and insights on how you can use those functions, classes and variables to get the best out of the engine. It also shares some cool and good to know secrets on how Cave works internally, so you can better use and understand it.

292 |

Keep in mind that this API is not a Python (language) tutorial and we expect that you have a basic understanding on how this programming language works and how to write code using it, as well as some Object Oriented Programming (OOP) knowledge. If you don't know Python, check this to get started.

293 |

How to read the API?

294 |

You can start reading it in order, as it appears in the Python API top menu, starting with the Core elements (Scene, Entity, Component) and then exploring all the others. Remember that you can always go back later and use this API as a reference while writting your own codes.

295 |

Do I need to install Python or anything?

296 |

No! Cave Engine comes with python embedded by default and all the cave modules and submodules are within the engine. Meaning that there is no need to install python by hand on your machine and you also don't need to install any cave modules yourself. In fact, it's not even possible to install it yourself since they only work inside Cave Engine.

297 |

Do you have any questions?

298 |

If you have any questions, suggestions or comments, feel free to Join one of our discord servers and ask there:

299 |
303 |
304 |
305 | 306 | 310 | 311 | 315 | 316 | 317 | 318 | 378 | 379 | 380 | 381 | -------------------------------------------------------------------------------- /css/base.css: -------------------------------------------------------------------------------- 1 | html { 2 | /* The nav header is 3.5rem high, plus 20px for the margin-top of the 3 | main container. */ 4 | scroll-padding-top: calc(3.5rem + 20px); 5 | } 6 | 7 | /* Replacement for `body { background-attachment: fixed; }`, which has 8 | performance issues when scrolling on large displays. See #1394. */ 9 | body::before { 10 | content: ' '; 11 | position: fixed; 12 | width: 100%; 13 | height: 100%; 14 | top: 0; 15 | left: 0; 16 | background-color: var(--bs-body-bg); 17 | background: url(../img/grid.png) repeat-x; 18 | will-change: transform; 19 | z-index: -1; 20 | } 21 | 22 | body > .container { 23 | margin-top: 20px; 24 | min-height: 400px; 25 | } 26 | 27 | .navbar.fixed-top { 28 | position: -webkit-sticky; 29 | position: sticky; 30 | } 31 | 32 | .source-links { 33 | float: right; 34 | } 35 | 36 | .col-md-9 img { 37 | max-width: 100%; 38 | display: inline-block; 39 | padding: 4px; 40 | line-height: 1.428571429; 41 | background-color: var(--bs-secondary-bg-subtle); 42 | border: 1px solid var(--bs-secondary-border-subtle); 43 | border-radius: 4px; 44 | margin: 20px auto 30px auto; 45 | } 46 | 47 | h1 { 48 | color: inherit; 49 | font-weight: 400; 50 | font-size: 42px; 51 | } 52 | 53 | h2, h3, h4, h5, h6 { 54 | color: inherit; 55 | font-weight: 300; 56 | } 57 | 58 | hr { 59 | border-top: 1px solid #aaa; 60 | opacity: 1; 61 | } 62 | 63 | pre, .rst-content tt { 64 | max-width: 100%; 65 | background-color: var(--bs-body-bg); 66 | border: solid 1px var(--bs-border-color); 67 | color: var(--bs-body-color); 68 | overflow-x: auto; 69 | } 70 | 71 | code.code-large, .rst-content tt.code-large { 72 | font-size: 90%; 73 | } 74 | 75 | code { 76 | padding: 2px 5px; 77 | background-color: rgba(var(--bs-body-bg-rgb), 0.75); 78 | border: solid 1px var(--bs-border-color); 79 | color: var(--bs-body-color); 80 | white-space: pre-wrap; 81 | word-wrap: break-word; 82 | } 83 | 84 | pre code { 85 | display: block; 86 | border: none; 87 | white-space: pre; 88 | word-wrap: normal; 89 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 90 | font-size: 12px; 91 | } 92 | 93 | kbd { 94 | padding: 2px 4px; 95 | font-size: 90%; 96 | color: var(--bs-secondary-text-emphasis); 97 | background-color: var(--bs-secondary-bg-subtle); 98 | border-radius: 3px; 99 | -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); 100 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); 101 | } 102 | 103 | a code { 104 | color: inherit; 105 | } 106 | 107 | a:hover code, a:focus code { 108 | color: inherit; 109 | } 110 | 111 | footer { 112 | margin-top: 30px; 113 | margin-bottom: 10px; 114 | text-align: center; 115 | font-weight: 200; 116 | } 117 | 118 | .modal-dialog { 119 | margin-top: 60px; 120 | } 121 | 122 | /* 123 | * Side navigation 124 | * 125 | * Scrollspy and affixed enhanced navigation to highlight sections and secondary 126 | * sections of docs content. 127 | */ 128 | 129 | .bs-sidebar.affix { 130 | position: -webkit-sticky; 131 | position: sticky; 132 | /* The nav header is 3.5rem high, plus 20px for the margin-top of the 133 | main container. */ 134 | top: calc(3.5rem + 20px); 135 | } 136 | 137 | .bs-sidebar.card { 138 | padding: 0; 139 | max-height: 90%; 140 | overflow-y: auto; 141 | } 142 | 143 | /* Toggle (vertically flip) sidebar collapse icon */ 144 | .bs-sidebar .navbar-toggler span { 145 | -moz-transform: scale(1, -1); 146 | -webkit-transform: scale(1, -1); 147 | -o-transform: scale(1, -1); 148 | -ms-transform: scale(1, -1); 149 | transform: scale(1, -1); 150 | } 151 | 152 | .bs-sidebar .navbar-toggler.collapsed span { 153 | -moz-transform: scale(1, 1); 154 | -webkit-transform: scale(1, 1); 155 | -o-transform: scale(1, 1); 156 | -ms-transform: scale(1, 1); 157 | transform: scale(1, 1); 158 | } 159 | 160 | /* First level of nav */ 161 | .bs-sidebar > .navbar-collapse > .nav { 162 | padding-top: 10px; 163 | padding-bottom: 10px; 164 | border-radius: 5px; 165 | width: 100%; 166 | } 167 | 168 | /* All levels of nav */ 169 | .bs-sidebar .nav > li > a { 170 | display: block; 171 | padding: 5px 20px; 172 | z-index: 1; 173 | } 174 | .bs-sidebar .nav > li > a:hover, 175 | .bs-sidebar .nav > li > a:focus { 176 | text-decoration: none; 177 | border-right: 1px solid; 178 | } 179 | .bs-sidebar .nav > li > a.active, 180 | .bs-sidebar .nav > li > a.active:hover, 181 | .bs-sidebar .nav > li > a.active:focus { 182 | font-weight: bold; 183 | background-color: transparent; 184 | border-right: 1px solid; 185 | } 186 | 187 | .bs-sidebar .nav .nav .nav { 188 | margin-left: 1em; 189 | } 190 | 191 | .bs-sidebar .nav > li > a { 192 | font-weight: bold; 193 | } 194 | 195 | .bs-sidebar .nav .nav > li > a { 196 | font-weight: normal; 197 | } 198 | 199 | .headerlink { 200 | font-family: FontAwesome; 201 | font-size: 14px; 202 | display: none; 203 | padding-left: .5em; 204 | text-decoration: none; 205 | vertical-align: middle; 206 | } 207 | 208 | h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink, h4:hover .headerlink, h5:hover .headerlink, h6:hover .headerlink { 209 | display:inline-block; 210 | } 211 | 212 | blockquote { 213 | padding-left: 10px; 214 | border-left: 4px solid #e6e6e6; 215 | } 216 | 217 | .admonition, details { 218 | padding: 15px; 219 | margin-bottom: 20px; 220 | border: 1px solid transparent; 221 | border-radius: 4px; 222 | text-align: left; 223 | } 224 | 225 | .admonition.note, details.note { 226 | color: var(--bs-primary-text-emphasis); 227 | background-color: var(--bs-primary-bg-subtle); 228 | border-color: var(--bs-primary-border-subtle); 229 | } 230 | 231 | .admonition.note h1, .admonition.note h2, .admonition.note h3, 232 | .admonition.note h4, .admonition.note h5, .admonition.note h6, 233 | details.note h1, details.note h2, details.note h3, 234 | details.note h4, details.note h5, details.note h6 { 235 | color: var(--bs-primary-text-emphasis); 236 | } 237 | 238 | .admonition.info, details.info { 239 | color: var(--bs-info-text-emphasis); 240 | background-color: var(--bs-info-bg-subtle); 241 | border-color: var(--bs-info-border-subtle); 242 | } 243 | 244 | .admonition.info h1, .admonition.info h2, .admonition.info h3, 245 | .admonition.info h4, .admonition.info h5, .admonition.info h6, 246 | details.info h1, details.info h2, details.info h3, 247 | details.info h4, details.info h5, details.info h6 { 248 | color: var(--bs-info-text-emphasis); 249 | } 250 | 251 | .admonition.warning, details.warning { 252 | color: var(--bs-warning-text-emphasis); 253 | background-color: var(--bs-warning-bg-subtle); 254 | border-color: var(--bs-warning-border-subtle); 255 | } 256 | 257 | .admonition.warning h1, .admonition.warning h2, .admonition.warning h3, 258 | .admonition.warning h4, .admonition.warning h5, .admonition.warning h6, 259 | details.warning h1, details.warning h2, details.warning h3, 260 | details.warning h4, details.warning h5, details.warning h6 { 261 | color: var(--bs-warning-text-emphasis); 262 | } 263 | 264 | .admonition.danger, details.danger { 265 | color: var(--bs-danger-text-emphasis); 266 | background-color: var(--bs-danger-bg-subtle); 267 | border-color: var(--bs-danger-border-subtle); 268 | } 269 | 270 | .admonition.danger h1, .admonition.danger h2, .admonition.danger h3, 271 | .admonition.danger h4, .admonition.danger h5, .admonition.danger h6, 272 | details.danger h1, details.danger h2, details.danger h3, 273 | details.danger h4, details.danger h5, details.danger h6 { 274 | color: var(--bs-danger-text-emphasis); 275 | } 276 | 277 | .admonition, details { 278 | color: var(--bs-light-text-emphasis); 279 | background-color: var(--bs-light-bg-subtle); 280 | border-color: var(--bs-light-border-subtle); 281 | } 282 | 283 | .admonition h1, .admonition h2, .admonition h3, 284 | .admonition h4, .admonition h5, .admonition h6, 285 | details h1, details h2, details h3, 286 | details h4, details h5, details h6 { 287 | color: var(--bs-light-text-emphasis); 288 | } 289 | 290 | .admonition-title, summary { 291 | font-weight: bold; 292 | text-align: left; 293 | } 294 | 295 | .admonition>p:last-child, details>p:last-child { 296 | margin-bottom: 0; 297 | } 298 | 299 | @media (max-width: 991.98px) { 300 | .navbar-collapse.show { 301 | overflow-y: auto; 302 | max-height: calc(100vh - 3.5rem); 303 | } 304 | } 305 | 306 | .dropdown-item.open { 307 | color: var(--bs-dropdown-link-active-color); 308 | background-color: var(--bs-dropdown-link-active-bg); 309 | } 310 | 311 | .dropdown-submenu > .dropdown-menu { 312 | margin: 0 0 0 1.5rem; 313 | padding: 0; 314 | border-width: 0; 315 | } 316 | 317 | .dropdown-submenu > a::after { 318 | display: block; 319 | content: " "; 320 | float: right; 321 | width: 0; 322 | height: 0; 323 | border-color: transparent; 324 | border-style: solid; 325 | border-width: 5px 0 5px 5px; 326 | border-left-color: var(--bs-dropdown-link-active-color); 327 | margin-top: 5px; 328 | margin-right: -10px; 329 | } 330 | 331 | .dropdown-submenu:hover > a::after { 332 | border-left-color: var(--bs-dropdown-link-active-color); 333 | } 334 | 335 | @media (min-width: 992px) { 336 | .dropdown-menu { 337 | overflow-y: auto; 338 | max-height: calc(100vh - 3.5rem); 339 | } 340 | 341 | .dropdown-submenu { 342 | position: relative; 343 | } 344 | 345 | .dropdown-submenu > .dropdown-menu { 346 | position: fixed !important; 347 | margin-top: -9px; 348 | margin-left: -2px; 349 | border-width: 1px; 350 | padding: 0.5rem 0; 351 | } 352 | 353 | .dropdown-submenu.pull-left { 354 | float: none; 355 | } 356 | 357 | .dropdown-submenu.pull-left > .dropdown-menu { 358 | left: -100%; 359 | margin-left: 10px; 360 | } 361 | } 362 | 363 | @media print { 364 | /* Remove sidebar when print */ 365 | .col-md-3 { display: none; } 366 | } 367 | -------------------------------------------------------------------------------- /css/brands.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | * Copyright 2023 Fonticons, Inc. 5 | */ 6 | :host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{content:"\f208"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-app-store:before{content:"\f36f"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-itunes-note:before{content:"\f3b5"}.fa-golang:before{content:"\e40f"}.fa-kickstarter:before{content:"\f3bb"}.fa-grav:before{content:"\f2d6"}.fa-weibo:before{content:"\f18a"}.fa-uncharted:before{content:"\e084"}.fa-firstdraft:before{content:"\f3a1"}.fa-square-youtube:before,.fa-youtube-square:before{content:"\f431"}.fa-wikipedia-w:before{content:"\f266"}.fa-rendact:before,.fa-wpressr:before{content:"\f3e4"}.fa-angellist:before{content:"\f209"}.fa-galactic-republic:before{content:"\f50c"}.fa-nfc-directional:before{content:"\e530"}.fa-skype:before{content:"\f17e"}.fa-joget:before{content:"\f3b7"}.fa-fedora:before{content:"\f798"}.fa-stripe-s:before{content:"\f42a"}.fa-meta:before{content:"\e49b"}.fa-laravel:before{content:"\f3bd"}.fa-hotjar:before{content:"\f3b1"}.fa-bluetooth-b:before{content:"\f294"}.fa-square-letterboxd:before{content:"\e62e"}.fa-sticker-mule:before{content:"\f3f7"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-hips:before{content:"\f452"}.fa-behance:before{content:"\f1b4"}.fa-reddit:before{content:"\f1a1"}.fa-discord:before{content:"\f392"}.fa-chrome:before{content:"\f268"}.fa-app-store-ios:before{content:"\f370"}.fa-cc-discover:before{content:"\f1f2"}.fa-wpbeginner:before{content:"\f297"}.fa-confluence:before{content:"\f78d"}.fa-shoelace:before{content:"\e60c"}.fa-mdb:before{content:"\f8ca"}.fa-dochub:before{content:"\f394"}.fa-accessible-icon:before{content:"\f368"}.fa-ebay:before{content:"\f4f4"}.fa-amazon:before{content:"\f270"}.fa-unsplash:before{content:"\e07c"}.fa-yarn:before{content:"\f7e3"}.fa-square-steam:before,.fa-steam-square:before{content:"\f1b7"}.fa-500px:before{content:"\f26e"}.fa-square-vimeo:before,.fa-vimeo-square:before{content:"\f194"}.fa-asymmetrik:before{content:"\f372"}.fa-font-awesome-flag:before,.fa-font-awesome-logo-full:before,.fa-font-awesome:before{content:"\f2b4"}.fa-gratipay:before{content:"\f184"}.fa-apple:before{content:"\f179"}.fa-hive:before{content:"\e07f"}.fa-gitkraken:before{content:"\f3a6"}.fa-keybase:before{content:"\f4f5"}.fa-apple-pay:before{content:"\f415"}.fa-padlet:before{content:"\e4a0"}.fa-amazon-pay:before{content:"\f42c"}.fa-github-square:before,.fa-square-github:before{content:"\f092"}.fa-stumbleupon:before{content:"\f1a4"}.fa-fedex:before{content:"\f797"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-shopify:before{content:"\e057"}.fa-neos:before{content:"\f612"}.fa-square-threads:before{content:"\e619"}.fa-hackerrank:before{content:"\f5f7"}.fa-researchgate:before{content:"\f4f8"}.fa-swift:before{content:"\f8e1"}.fa-angular:before{content:"\f420"}.fa-speakap:before{content:"\f3f3"}.fa-angrycreative:before{content:"\f36e"}.fa-y-combinator:before{content:"\f23b"}.fa-empire:before{content:"\f1d1"}.fa-envira:before{content:"\f299"}.fa-google-scholar:before{content:"\e63b"}.fa-gitlab-square:before,.fa-square-gitlab:before{content:"\e5ae"}.fa-studiovinari:before{content:"\f3f8"}.fa-pied-piper:before{content:"\f2ae"}.fa-wordpress:before{content:"\f19a"}.fa-product-hunt:before{content:"\f288"}.fa-firefox:before{content:"\f269"}.fa-linode:before{content:"\f2b8"}.fa-goodreads:before{content:"\f3a8"}.fa-odnoklassniki-square:before,.fa-square-odnoklassniki:before{content:"\f264"}.fa-jsfiddle:before{content:"\f1cc"}.fa-sith:before{content:"\f512"}.fa-themeisle:before{content:"\f2b2"}.fa-page4:before{content:"\f3d7"}.fa-hashnode:before{content:"\e499"}.fa-react:before{content:"\f41b"}.fa-cc-paypal:before{content:"\f1f4"}.fa-squarespace:before{content:"\f5be"}.fa-cc-stripe:before{content:"\f1f5"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-bitcoin:before{content:"\f379"}.fa-keycdn:before{content:"\f3ba"}.fa-opera:before{content:"\f26a"}.fa-itch-io:before{content:"\f83a"}.fa-umbraco:before{content:"\f8e8"}.fa-galactic-senate:before{content:"\f50d"}.fa-ubuntu:before{content:"\f7df"}.fa-draft2digital:before{content:"\f396"}.fa-stripe:before{content:"\f429"}.fa-houzz:before{content:"\f27c"}.fa-gg:before{content:"\f260"}.fa-dhl:before{content:"\f790"}.fa-pinterest-square:before,.fa-square-pinterest:before{content:"\f0d3"}.fa-xing:before{content:"\f168"}.fa-blackberry:before{content:"\f37b"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-playstation:before{content:"\f3df"}.fa-quinscape:before{content:"\f459"}.fa-less:before{content:"\f41d"}.fa-blogger-b:before{content:"\f37d"}.fa-opencart:before{content:"\f23d"}.fa-vine:before{content:"\f1ca"}.fa-signal-messenger:before{content:"\e663"}.fa-paypal:before{content:"\f1ed"}.fa-gitlab:before{content:"\f296"}.fa-typo3:before{content:"\f42b"}.fa-reddit-alien:before{content:"\f281"}.fa-yahoo:before{content:"\f19e"}.fa-dailymotion:before{content:"\e052"}.fa-affiliatetheme:before{content:"\f36b"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-bootstrap:before{content:"\f836"}.fa-odnoklassniki:before{content:"\f263"}.fa-nfc-symbol:before{content:"\e531"}.fa-mintbit:before{content:"\e62f"}.fa-ethereum:before{content:"\f42e"}.fa-speaker-deck:before{content:"\f83c"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-patreon:before{content:"\f3d9"}.fa-avianex:before{content:"\f374"}.fa-ello:before{content:"\f5f1"}.fa-gofore:before{content:"\f3a7"}.fa-bimobject:before{content:"\f378"}.fa-brave-reverse:before{content:"\e63d"}.fa-facebook-f:before{content:"\f39e"}.fa-google-plus-square:before,.fa-square-google-plus:before{content:"\f0d4"}.fa-mandalorian:before{content:"\f50f"}.fa-first-order-alt:before{content:"\f50a"}.fa-osi:before{content:"\f41a"}.fa-google-wallet:before{content:"\f1ee"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-periscope:before{content:"\f3da"}.fa-fulcrum:before{content:"\f50b"}.fa-cloudscale:before{content:"\f383"}.fa-forumbee:before{content:"\f211"}.fa-mizuni:before{content:"\f3cc"}.fa-schlix:before{content:"\f3ea"}.fa-square-xing:before,.fa-xing-square:before{content:"\f169"}.fa-bandcamp:before{content:"\f2d5"}.fa-wpforms:before{content:"\f298"}.fa-cloudversify:before{content:"\f385"}.fa-usps:before{content:"\f7e1"}.fa-megaport:before{content:"\f5a3"}.fa-magento:before{content:"\f3c4"}.fa-spotify:before{content:"\f1bc"}.fa-optin-monster:before{content:"\f23c"}.fa-fly:before{content:"\f417"}.fa-aviato:before{content:"\f421"}.fa-itunes:before{content:"\f3b4"}.fa-cuttlefish:before{content:"\f38c"}.fa-blogger:before{content:"\f37c"}.fa-flickr:before{content:"\f16e"}.fa-viber:before{content:"\f409"}.fa-soundcloud:before{content:"\f1be"}.fa-digg:before{content:"\f1a6"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-letterboxd:before{content:"\e62d"}.fa-symfony:before{content:"\f83d"}.fa-maxcdn:before{content:"\f136"}.fa-etsy:before{content:"\f2d7"}.fa-facebook-messenger:before{content:"\f39f"}.fa-audible:before{content:"\f373"}.fa-think-peaks:before{content:"\f731"}.fa-bilibili:before{content:"\e3d9"}.fa-erlang:before{content:"\f39d"}.fa-x-twitter:before{content:"\e61b"}.fa-cotton-bureau:before{content:"\f89e"}.fa-dashcube:before{content:"\f210"}.fa-42-group:before,.fa-innosoft:before{content:"\e080"}.fa-stack-exchange:before{content:"\f18d"}.fa-elementor:before{content:"\f430"}.fa-pied-piper-square:before,.fa-square-pied-piper:before{content:"\e01e"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-palfed:before{content:"\f3d8"}.fa-superpowers:before{content:"\f2dd"}.fa-resolving:before{content:"\f3e7"}.fa-xbox:before{content:"\f412"}.fa-searchengin:before{content:"\f3eb"}.fa-tiktok:before{content:"\e07b"}.fa-facebook-square:before,.fa-square-facebook:before{content:"\f082"}.fa-renren:before{content:"\f18b"}.fa-linux:before{content:"\f17c"}.fa-glide:before{content:"\f2a5"}.fa-linkedin:before{content:"\f08c"}.fa-hubspot:before{content:"\f3b2"}.fa-deploydog:before{content:"\f38e"}.fa-twitch:before{content:"\f1e8"}.fa-ravelry:before{content:"\f2d9"}.fa-mixer:before{content:"\e056"}.fa-lastfm-square:before,.fa-square-lastfm:before{content:"\f203"}.fa-vimeo:before{content:"\f40a"}.fa-mendeley:before{content:"\f7b3"}.fa-uniregistry:before{content:"\f404"}.fa-figma:before{content:"\f799"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-dropbox:before{content:"\f16b"}.fa-instagram:before{content:"\f16d"}.fa-cmplid:before{content:"\e360"}.fa-upwork:before{content:"\e641"}.fa-facebook:before{content:"\f09a"}.fa-gripfire:before{content:"\f3ac"}.fa-jedi-order:before{content:"\f50e"}.fa-uikit:before{content:"\f403"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-phabricator:before{content:"\f3db"}.fa-ussunnah:before{content:"\f407"}.fa-earlybirds:before{content:"\f39a"}.fa-trade-federation:before{content:"\f513"}.fa-autoprefixer:before{content:"\f41c"}.fa-whatsapp:before{content:"\f232"}.fa-slideshare:before{content:"\f1e7"}.fa-google-play:before{content:"\f3ab"}.fa-viadeo:before{content:"\f2a9"}.fa-line:before{content:"\f3c0"}.fa-google-drive:before{content:"\f3aa"}.fa-servicestack:before{content:"\f3ec"}.fa-simplybuilt:before{content:"\f215"}.fa-bitbucket:before{content:"\f171"}.fa-imdb:before{content:"\f2d8"}.fa-deezer:before{content:"\e077"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-jira:before{content:"\f7b1"}.fa-docker:before{content:"\f395"}.fa-screenpal:before{content:"\e570"}.fa-bluetooth:before{content:"\f293"}.fa-gitter:before{content:"\f426"}.fa-d-and-d:before{content:"\f38d"}.fa-microblog:before{content:"\e01a"}.fa-cc-diners-club:before{content:"\f24c"}.fa-gg-circle:before{content:"\f261"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-yandex:before{content:"\f413"}.fa-readme:before{content:"\f4d5"}.fa-html5:before{content:"\f13b"}.fa-sellsy:before{content:"\f213"}.fa-sass:before{content:"\f41e"}.fa-wirsindhandwerk:before,.fa-wsh:before{content:"\e2d0"}.fa-buromobelexperte:before{content:"\f37f"}.fa-salesforce:before{content:"\f83b"}.fa-octopus-deploy:before{content:"\e082"}.fa-medapps:before{content:"\f3c6"}.fa-ns8:before{content:"\f3d5"}.fa-pinterest-p:before{content:"\f231"}.fa-apper:before{content:"\f371"}.fa-fort-awesome:before{content:"\f286"}.fa-waze:before{content:"\f83f"}.fa-cc-jcb:before{content:"\f24b"}.fa-snapchat-ghost:before,.fa-snapchat:before{content:"\f2ab"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-rust:before{content:"\e07a"}.fa-wix:before{content:"\f5cf"}.fa-behance-square:before,.fa-square-behance:before{content:"\f1b5"}.fa-supple:before{content:"\f3f9"}.fa-webflow:before{content:"\e65c"}.fa-rebel:before{content:"\f1d0"}.fa-css3:before{content:"\f13c"}.fa-staylinked:before{content:"\f3f5"}.fa-kaggle:before{content:"\f5fa"}.fa-space-awesome:before{content:"\e5ac"}.fa-deviantart:before{content:"\f1bd"}.fa-cpanel:before{content:"\f388"}.fa-goodreads-g:before{content:"\f3a9"}.fa-git-square:before,.fa-square-git:before{content:"\f1d2"}.fa-square-tumblr:before,.fa-tumblr-square:before{content:"\f174"}.fa-trello:before{content:"\f181"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-get-pocket:before{content:"\f265"}.fa-perbyte:before{content:"\e083"}.fa-grunt:before{content:"\f3ad"}.fa-weebly:before{content:"\f5cc"}.fa-connectdevelop:before{content:"\f20e"}.fa-leanpub:before{content:"\f212"}.fa-black-tie:before{content:"\f27e"}.fa-themeco:before{content:"\f5c6"}.fa-python:before{content:"\f3e2"}.fa-android:before{content:"\f17b"}.fa-bots:before{content:"\e340"}.fa-free-code-camp:before{content:"\f2c5"}.fa-hornbill:before{content:"\f592"}.fa-js:before{content:"\f3b8"}.fa-ideal:before{content:"\e013"}.fa-git:before{content:"\f1d3"}.fa-dev:before{content:"\f6cc"}.fa-sketch:before{content:"\f7c6"}.fa-yandex-international:before{content:"\f414"}.fa-cc-amex:before{content:"\f1f3"}.fa-uber:before{content:"\f402"}.fa-github:before{content:"\f09b"}.fa-php:before{content:"\f457"}.fa-alipay:before{content:"\f642"}.fa-youtube:before{content:"\f167"}.fa-skyatlas:before{content:"\f216"}.fa-firefox-browser:before{content:"\e007"}.fa-replyd:before{content:"\f3e6"}.fa-suse:before{content:"\f7d6"}.fa-jenkins:before{content:"\f3b6"}.fa-twitter:before{content:"\f099"}.fa-rockrms:before{content:"\f3e9"}.fa-pinterest:before{content:"\f0d2"}.fa-buffer:before{content:"\f837"}.fa-npm:before{content:"\f3d4"}.fa-yammer:before{content:"\f840"}.fa-btc:before{content:"\f15a"}.fa-dribbble:before{content:"\f17d"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-internet-explorer:before{content:"\f26b"}.fa-stubber:before{content:"\e5c7"}.fa-telegram-plane:before,.fa-telegram:before{content:"\f2c6"}.fa-old-republic:before{content:"\f510"}.fa-odysee:before{content:"\e5c6"}.fa-square-whatsapp:before,.fa-whatsapp-square:before{content:"\f40c"}.fa-node-js:before{content:"\f3d3"}.fa-edge-legacy:before{content:"\e078"}.fa-slack-hash:before,.fa-slack:before{content:"\f198"}.fa-medrt:before{content:"\f3c8"}.fa-usb:before{content:"\f287"}.fa-tumblr:before{content:"\f173"}.fa-vaadin:before{content:"\f408"}.fa-quora:before{content:"\f2c4"}.fa-square-x-twitter:before{content:"\e61a"}.fa-reacteurope:before{content:"\f75d"}.fa-medium-m:before,.fa-medium:before{content:"\f23a"}.fa-amilia:before{content:"\f36d"}.fa-mixcloud:before{content:"\f289"}.fa-flipboard:before{content:"\f44d"}.fa-viacoin:before{content:"\f237"}.fa-critical-role:before{content:"\f6c9"}.fa-sitrox:before{content:"\e44a"}.fa-discourse:before{content:"\f393"}.fa-joomla:before{content:"\f1aa"}.fa-mastodon:before{content:"\f4f6"}.fa-airbnb:before{content:"\f834"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-buy-n-large:before{content:"\f8a6"}.fa-gulp:before{content:"\f3ae"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-strava:before{content:"\f428"}.fa-ember:before{content:"\f423"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-teamspeak:before{content:"\f4f9"}.fa-pushed:before{content:"\f3e1"}.fa-wordpress-simple:before{content:"\f411"}.fa-nutritionix:before{content:"\f3d6"}.fa-wodu:before{content:"\e088"}.fa-google-pay:before{content:"\e079"}.fa-intercom:before{content:"\f7af"}.fa-zhihu:before{content:"\f63f"}.fa-korvue:before{content:"\f42f"}.fa-pix:before{content:"\e43a"}.fa-steam-symbol:before{content:"\f3f6"} -------------------------------------------------------------------------------- /css/solid.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | * Copyright 2023 Fonticons, Inc. 5 | */ 6 | :host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900} -------------------------------------------------------------------------------- /css/v4-font-face.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | * Copyright 2023 Fonticons, Inc. 5 | */ 6 | @font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a} -------------------------------------------------------------------------------- /engine.pyi: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | def getEvents() -> Events: ... 4 | def getMousePosition() -> Vector2: ... 5 | def setMousePosition(int x, int y) -> None: ... 6 | 7 | def getWindowSize() -> cave.Vector2: ... 8 | def quitGame() -> None: ... 9 | def getCurrentScene() -> Scene: ... 10 | def setScene(sceneName : str) -> None: ... 11 | 12 | def restartCurrentScene() -> None: ... 13 | 14 | class Events: 15 | def pressed(self, event : str) -> bool: ... 16 | def active(self, event : str) -> bool: ... 17 | def released(self, event : str) -> bool: ... 18 | 19 | 20 | class Entity: 21 | name : str 22 | def kill(): ... 23 | def hasTag(tag : str) -> bool: ... 24 | def add(component : Component) -> None: ... 25 | def get(component : str) -> Component: ... 26 | def getAll(component : str) -> list(Component): ... 27 | def getScene() -> Scene: ... 28 | def getParent() -> Entity: ... 29 | def getChildren() -> list(Entity): ... 30 | def getTransform() -> TransformComponent: ... 31 | def getID() -> int: ... 32 | 33 | 34 | class RayCastOut: 35 | hit : bool 36 | position : Vector3 37 | normal : Vector3 38 | entity : Entity 39 | 40 | 41 | class Scene: 42 | def newEntity() -> Entity: ... 43 | def add(entity : Entity) -> Entity: ... 44 | def addFromTemplate(templateName : str, overrideTransform=True) -> Entity: ... 45 | def remove(entity : Entity) -> None: ... 46 | def rayCast(origin : Vector3, target : Vector3) -> RayCastOut: ... 47 | def getSun() -> Sun: ... 48 | 49 | 50 | class Sun: 51 | hour : float # 0.0 to 24.0 52 | angle : float #0.0 to 360.0 53 | color : Vector3 54 | intensity : float 55 | 56 | 57 | class Timer: 58 | def get() -> float: ... 59 | def set(value : float) -> None: ... 60 | def reset() -> None: ... 61 | 62 | 63 | ############################################################################### 64 | 65 | 66 | class Component: 67 | entity : Entity 68 | 69 | def start(scene : Scene)-> None: 70 | """Override thid Method and it will be called by the entity when added to the scene.""" 71 | pass 72 | 73 | def update()-> None: 74 | """Override thid Method and it will be called every frame.""" 75 | pass 76 | 77 | def end(scene : Scene)-> None: 78 | """Override thid Method and it will be called by the entity when removed from the scene.""" 79 | pass 80 | 81 | 82 | class TransformComponent(Component): 83 | position : Vector3 84 | scale : Vector3 85 | 86 | def getEuler() -> Vector3: ... 87 | def setEuler(euler : Vector3): ... 88 | def setEuler(x : float, y : float, z : float): ... 89 | 90 | def getQuaternion() -> Quaternion: ... 91 | def setQuaternion(quaternion : Quaternion): ... 92 | def setQuaternion(x : float, y : float, z : float, w: float): ... 93 | 94 | def getMatrix() -> Matrix4: ... 95 | def setMatrix(mat : Matrix4): ... 96 | 97 | def rotateVector(vec : Vector3) -> Vector3: ... 98 | def transformVector(vec : Vector3) -> Vector3: ... 99 | 100 | def rotate(x : float, y : float, z : float) -> None: ... 101 | def move(x : float, y : float, z : float, local = True): ... 102 | 103 | def rotateOnAxis(angle : float, axis : Vector3) -> None: ... 104 | def rotateOnPitch(angle : float) -> None: ... 105 | def rotateOnYaw(angle : float) -> None: ... 106 | def rotateOnRoll(angle : float) -> None: ... 107 | def applyLocalMovement(x : float, y : float, z : float) -> None: ... 108 | def getPitch() -> float: ... 109 | def getYaw() -> float: ... 110 | def getRoll() -> float: ... 111 | def getForwardVector() -> Vector3: ... 112 | def getRightVector() -> Vector3: ... 113 | def getUpVector() -> Vector3: ... 114 | def lookAt(direction : Vector3, up = Vector3(0, 1, 0)) -> None: ... 115 | 116 | 117 | class MeshComponent(Component): 118 | def setAnimation(animation : string) -> None: ... 119 | 120 | 121 | class LightComponent(Component): 122 | color : Vector3 123 | radius : float 124 | intensity : float 125 | 126 | 127 | class UIElementComponent(Component): 128 | text : str 129 | position : UIVector 130 | scale : UIVector 131 | text : str 132 | 133 | def isHovered() -> bool: ... 134 | 135 | 136 | class RigidBodyComponent(Component): 137 | alwaysActive : bool 138 | linearVelocity : cave.Vector3 139 | angularVelocity : cave.Vector3 140 | angularFactor : cave.Vector3 141 | 142 | def getCollisions() -> list(Entity): ... 143 | def collidedWith(tag : string) -> bool: ... 144 | def applyTorque(x : float, y : float, z : float) -> None: ... 145 | def applyForce(x : float, y : float, z : float, location : Vector3) -> None: ... 146 | def isDynamic() -> bool: ... 147 | def setMass(value : float) -> None: ... 148 | 149 | 150 | ############################################################################### 151 | # Math 152 | 153 | 154 | def normalized(vec : Vector3) -> Vector3: ... 155 | 156 | def length(vec : Vector3) -> float: ... 157 | 158 | 159 | class Vector2: 160 | x : float 161 | y : float 162 | 163 | # Equivalents: 164 | s : float 165 | t : float 166 | 167 | x : float 168 | y : float 169 | 170 | 171 | class Vector3: 172 | x : float 173 | y : float 174 | z : float 175 | 176 | # Equivalents: 177 | r : float 178 | g : float 179 | b : float 180 | 181 | 182 | class Vector4: 183 | x : float 184 | y : float 185 | z : float 186 | w : float 187 | 188 | # Equivalents: 189 | r : float 190 | g : float 191 | b : float 192 | a : float 193 | 194 | 195 | class Quaternion: 196 | x : float 197 | y : float 198 | z : float 199 | w : float 200 | 201 | 202 | class UIVector: 203 | anchoringX : int # -1, 0, 1 204 | anchoringY : int # -1, 0, 1 205 | 206 | def isRelativeX() -> bool: ... 207 | def isRelativeY() -> bool: ... 208 | def getX(parentScale = 1.0) -> float: ... 209 | def getY(parentScale = 1.0) -> float: ... 210 | def setPixelX(value : int) -> None: ... 211 | def setPixelY(value : int) -> None: ... 212 | def setPixel(x : int, y : int) -> None: ... 213 | def setRelativeX(value : float) -> None: ... 214 | def setRelativeY(value : float) -> None: ... 215 | def setRelative(x : float, y : float) -> None: ... -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/img/favicon.ico -------------------------------------------------------------------------------- /img/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/img/grid.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Cave Engine Docs 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 252 | 253 |
254 |
255 |
282 |
283 | 284 |

285 |

Welcome to Cave Engine's Docs

286 |

(Use the top menu to navigate the categories)

287 |

Cave Engine is a Simple, easy to use, 3D desktop Game Engine that is scriptable in Python. You can use it to make any type of games you want and release them commercially.

288 |

You can expect a seamless development process with cave, with pretty much ZERO loading time: it does not require any Shader or Code compilation and asset handling is as fast as possible!

289 |

In this website you'll find some useful information such as the future roadmap and license.

290 |

Get Cave Engine

291 |

You can Purchase Cave Engine on itch by clicking here:

292 | 293 | 294 |

Alternatively, you can get access to it by becoming a Solid Patreon.

295 |
296 |

Our Discord Server

297 |

If you want to talk about the engine, leave some suggestions, comments or get some help from the community, feel free to join us:

298 | 302 |

We have a Portuguese and an English discord so you can feel free to join the one you're more confortable with.

303 |
304 |
305 | 306 | 310 | 311 | 315 | 316 | 317 | 318 | 378 | 379 | 380 | 381 | 382 | 386 | -------------------------------------------------------------------------------- /js/base.js: -------------------------------------------------------------------------------- 1 | function getSearchTerm() { 2 | var sPageURL = window.location.search.substring(1); 3 | var sURLVariables = sPageURL.split('&'); 4 | for (var i = 0; i < sURLVariables.length; i++) { 5 | var sParameterName = sURLVariables[i].split('='); 6 | if (sParameterName[0] == 'q') { 7 | return sParameterName[1]; 8 | } 9 | } 10 | } 11 | 12 | function applyTopPadding() { 13 | // Update various absolute positions to match where the main container 14 | // starts. This is necessary for handling multi-line nav headers, since 15 | // that pushes the main container down. 16 | var container = document.querySelector('body > .container'); 17 | var offset = container.offsetTop; 18 | 19 | document.documentElement.style.scrollPaddingTop = offset + 'px'; 20 | document.querySelectorAll('.bs-sidebar.affix').forEach(function(sidebar) { 21 | sidebar.style.top = offset + 'px'; 22 | }); 23 | } 24 | 25 | document.addEventListener("DOMContentLoaded", function () { 26 | var search_term = getSearchTerm(); 27 | var search_modal = new bootstrap.Modal(document.getElementById('mkdocs_search_modal')); 28 | var keyboard_modal = new bootstrap.Modal(document.getElementById('mkdocs_keyboard_modal')); 29 | 30 | if (search_term) { 31 | search_modal.show(); 32 | } 33 | 34 | // make sure search input gets autofocus every time modal opens. 35 | document.getElementById('mkdocs_search_modal').addEventListener('shown.bs.modal', function() { 36 | document.getElementById('mkdocs-search-query').focus(); 37 | }); 38 | 39 | // Close search modal when result is selected 40 | // The links get added later so listen to parent 41 | document.getElementById('mkdocs-search-results').addEventListener('click', function(e) { 42 | if (e.target.tagName === 'A') { 43 | search_modal.hide(); 44 | } 45 | }); 46 | 47 | // Populate keyboard modal with proper Keys 48 | document.querySelector('.help.shortcut kbd').innerHTML = keyCodes[shortcuts.help]; 49 | document.querySelector('.prev.shortcut kbd').innerHTML = keyCodes[shortcuts.previous]; 50 | document.querySelector('.next.shortcut kbd').innerHTML = keyCodes[shortcuts.next]; 51 | document.querySelector('.search.shortcut kbd').innerHTML = keyCodes[shortcuts.search]; 52 | 53 | // Keyboard navigation 54 | document.addEventListener("keydown", function(e) { 55 | if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return true; 56 | var key = e.which || e.keyCode || window.event && window.event.keyCode; 57 | var page; 58 | switch (key) { 59 | case shortcuts.next: 60 | page = document.querySelector('.navbar a[rel="next"]'); 61 | break; 62 | case shortcuts.previous: 63 | page = document.querySelector('.navbar a[rel="prev"]'); 64 | break; 65 | case shortcuts.search: 66 | e.preventDefault(); 67 | keyboard_modal.hide(); 68 | search_modal.show(); 69 | document.getElementById('mkdocs-search-query').focus(); 70 | break; 71 | case shortcuts.help: 72 | search_modal.hide(); 73 | keyboard_modal.show(); 74 | break; 75 | default: break; 76 | } 77 | if (page && page.hasAttribute('href')) { 78 | keyboard_modal.hide(); 79 | window.location.href = page.getAttribute('href'); 80 | } 81 | }); 82 | 83 | document.querySelectorAll('table').forEach(function(table) { 84 | table.classList.add('table', 'table-striped', 'table-hover'); 85 | }); 86 | 87 | function showInnerDropdown(item) { 88 | var popup = item.nextElementSibling; 89 | popup.classList.add('show'); 90 | item.classList.add('open'); 91 | 92 | // First, close any sibling dropdowns. 93 | var container = item.parentElement.parentElement; 94 | container.querySelectorAll(':scope > .dropdown-submenu > a').forEach(function(el) { 95 | if (el !== item) { 96 | hideInnerDropdown(el); 97 | } 98 | }); 99 | 100 | var popupMargin = 10; 101 | var maxBottom = window.innerHeight - popupMargin; 102 | var bounds = item.getBoundingClientRect(); 103 | 104 | popup.style.left = bounds.right + 'px'; 105 | if (bounds.top + popup.clientHeight > maxBottom && 106 | bounds.top > window.innerHeight / 2) { 107 | popup.style.top = (bounds.bottom - popup.clientHeight) + 'px'; 108 | popup.style.maxHeight = (bounds.bottom - popupMargin) + 'px'; 109 | } else { 110 | popup.style.top = bounds.top + 'px'; 111 | popup.style.maxHeight = (maxBottom - bounds.top) + 'px'; 112 | } 113 | } 114 | 115 | function hideInnerDropdown(item) { 116 | var popup = item.nextElementSibling; 117 | popup.classList.remove('show'); 118 | item.classList.remove('open'); 119 | 120 | popup.scrollTop = 0; 121 | var menu = popup.querySelector('.dropdown-menu'); 122 | if (menu) { 123 | menu.scrollTop = 0; 124 | } 125 | var dropdown = popup.querySelector('.dropdown-submenu > a'); 126 | if (dropdown) { 127 | dropdown.classList.remove('open'); 128 | } 129 | } 130 | 131 | document.querySelectorAll('.dropdown-submenu > a').forEach(function(item) { 132 | item.addEventListener('click', function(e) { 133 | if (item.nextElementSibling.classList.contains('show')) { 134 | hideInnerDropdown(item); 135 | } else { 136 | showInnerDropdown(item); 137 | } 138 | 139 | e.stopPropagation(); 140 | e.preventDefault(); 141 | }); 142 | }); 143 | 144 | document.querySelectorAll('.dropdown-menu').forEach(function(menu) { 145 | menu.parentElement.addEventListener('hide.bs.dropdown', function() { 146 | menu.scrollTop = 0; 147 | var dropdown = menu.querySelector('.dropdown-submenu > a'); 148 | if (dropdown) { 149 | dropdown.classList.remove('open'); 150 | } 151 | menu.querySelectorAll('.dropdown-menu .dropdown-menu').forEach(function(submenu) { 152 | submenu.classList.remove('show'); 153 | }); 154 | }); 155 | }); 156 | 157 | applyTopPadding(); 158 | }); 159 | 160 | window.addEventListener('resize', applyTopPadding); 161 | 162 | var scrollSpy = new bootstrap.ScrollSpy(document.body, { 163 | target: '.bs-sidebar' 164 | }); 165 | 166 | /* Prevent disabled links from causing a page reload */ 167 | document.querySelectorAll("li.disabled a").forEach(function(item) { 168 | item.addEventListener("click", function(event) { 169 | event.preventDefault(); 170 | }); 171 | }); 172 | 173 | // See https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes 174 | // We only list common keys below. Obscure keys are omitted and their use is discouraged. 175 | var keyCodes = { 176 | 8: 'backspace', 177 | 9: 'tab', 178 | 13: 'enter', 179 | 16: 'shift', 180 | 17: 'ctrl', 181 | 18: 'alt', 182 | 19: 'pause/break', 183 | 20: 'caps lock', 184 | 27: 'escape', 185 | 32: 'spacebar', 186 | 33: 'page up', 187 | 34: 'page down', 188 | 35: 'end', 189 | 36: 'home', 190 | 37: '←', 191 | 38: '↑', 192 | 39: '→', 193 | 40: '↓', 194 | 45: 'insert', 195 | 46: 'delete', 196 | 48: '0', 197 | 49: '1', 198 | 50: '2', 199 | 51: '3', 200 | 52: '4', 201 | 53: '5', 202 | 54: '6', 203 | 55: '7', 204 | 56: '8', 205 | 57: '9', 206 | 65: 'a', 207 | 66: 'b', 208 | 67: 'c', 209 | 68: 'd', 210 | 69: 'e', 211 | 70: 'f', 212 | 71: 'g', 213 | 72: 'h', 214 | 73: 'i', 215 | 74: 'j', 216 | 75: 'k', 217 | 76: 'l', 218 | 77: 'm', 219 | 78: 'n', 220 | 79: 'o', 221 | 80: 'p', 222 | 81: 'q', 223 | 82: 'r', 224 | 83: 's', 225 | 84: 't', 226 | 85: 'u', 227 | 86: 'v', 228 | 87: 'w', 229 | 88: 'x', 230 | 89: 'y', 231 | 90: 'z', 232 | 91: 'Left Windows Key / Left ⌘', 233 | 92: 'Right Windows Key', 234 | 93: 'Windows Menu / Right ⌘', 235 | 96: 'numpad 0', 236 | 97: 'numpad 1', 237 | 98: 'numpad 2', 238 | 99: 'numpad 3', 239 | 100: 'numpad 4', 240 | 101: 'numpad 5', 241 | 102: 'numpad 6', 242 | 103: 'numpad 7', 243 | 104: 'numpad 8', 244 | 105: 'numpad 9', 245 | 106: 'multiply', 246 | 107: 'add', 247 | 109: 'subtract', 248 | 110: 'decimal point', 249 | 111: 'divide', 250 | 112: 'f1', 251 | 113: 'f2', 252 | 114: 'f3', 253 | 115: 'f4', 254 | 116: 'f5', 255 | 117: 'f6', 256 | 118: 'f7', 257 | 119: 'f8', 258 | 120: 'f9', 259 | 121: 'f10', 260 | 122: 'f11', 261 | 123: 'f12', 262 | 124: 'f13', 263 | 125: 'f14', 264 | 126: 'f15', 265 | 127: 'f16', 266 | 128: 'f17', 267 | 129: 'f18', 268 | 130: 'f19', 269 | 131: 'f20', 270 | 132: 'f21', 271 | 133: 'f22', 272 | 134: 'f23', 273 | 135: 'f24', 274 | 144: 'num lock', 275 | 145: 'scroll lock', 276 | 186: ';', 277 | 187: '=', 278 | 188: ',', 279 | 189: '‐', 280 | 190: '.', 281 | 191: '?', 282 | 192: '`', 283 | 219: '[', 284 | 220: '\', 285 | 221: ']', 286 | 222: ''', 287 | }; 288 | -------------------------------------------------------------------------------- /js/darkmode.js: -------------------------------------------------------------------------------- 1 | function setColorMode(mode) { 2 | // Switch between light/dark theme. `mode` is a string value of either 'dark' or 'light'. 3 | var hljs_light = document.getElementById('hljs-light'), 4 | hljs_dark = document.getElementById('hljs-dark'); 5 | document.documentElement.setAttribute('data-bs-theme', mode); 6 | if (mode == 'dark') { 7 | hljs_light.disabled = true; 8 | hljs_dark.disabled = false; 9 | } else { 10 | hljs_dark.disabled = true; 11 | hljs_light.disabled = false; 12 | } 13 | } 14 | 15 | function updateModeToggle(mode) { 16 | // Update icon and toggle checkmarks of color mode selector. 17 | var menu = document.getElementById('theme-menu'); 18 | document.querySelectorAll('[data-bs-theme-value]') 19 | .forEach(function(toggle) { 20 | if (mode == toggle.getAttribute('data-bs-theme-value')) { 21 | toggle.setAttribute('aria-pressed', 'true'); 22 | toggle.lastElementChild.classList.remove('d-none'); 23 | menu.firstElementChild.setAttribute('class', toggle.firstElementChild.getAttribute('class')); 24 | } else { 25 | toggle.setAttribute('aria-pressed', 'false'); 26 | toggle.lastElementChild.classList.add('d-none'); 27 | } 28 | }); 29 | } 30 | 31 | function onSystemColorSchemeChange(event) { 32 | // Update site color mode to match system color mode. 33 | setColorMode(event.matches ? 'dark' : 'light'); 34 | } 35 | 36 | var mql = window.matchMedia('(prefers-color-scheme: dark)'), 37 | defaultMode = document.documentElement.getAttribute('data-bs-theme'), 38 | storedMode = localStorage.getItem('mkdocs-colormode'); 39 | if (storedMode && storedMode != 'auto') { 40 | setColorMode(storedMode); 41 | updateModeToggle(storedMode); 42 | } else if (storedMode == 'auto' || defaultMode == 'auto') { 43 | setColorMode(mql.matches ? 'dark' : 'light'); 44 | updateModeToggle('auto'); 45 | mql.addEventListener('change', onSystemColorSchemeChange); 46 | } else { 47 | setColorMode(defaultMode); 48 | updateModeToggle(defaultMode); 49 | } 50 | 51 | document.querySelectorAll('[data-bs-theme-value]') 52 | .forEach(function(toggle) { 53 | toggle.addEventListener('click', function (e) { 54 | var mode = e.currentTarget.getAttribute('data-bs-theme-value'); 55 | localStorage.setItem('mkdocs-colormode', mode); 56 | if (mode == 'auto') { 57 | setColorMode(mql.matches ? 'dark' : 'light'); 58 | mql.addEventListener('change', onSystemColorSchemeChange); 59 | } else { 60 | setColorMode(mode); 61 | mql.removeEventListener('change', onSystemColorSchemeChange); 62 | } 63 | updateModeToggle(mode); 64 | }); 65 | }); 66 | -------------------------------------------------------------------------------- /search/main.js: -------------------------------------------------------------------------------- 1 | function getSearchTermFromLocation() { 2 | var sPageURL = window.location.search.substring(1); 3 | var sURLVariables = sPageURL.split('&'); 4 | for (var i = 0; i < sURLVariables.length; i++) { 5 | var sParameterName = sURLVariables[i].split('='); 6 | if (sParameterName[0] == 'q') { 7 | return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20')); 8 | } 9 | } 10 | } 11 | 12 | function joinUrl (base, path) { 13 | if (path.substring(0, 1) === "/") { 14 | // path starts with `/`. Thus it is absolute. 15 | return path; 16 | } 17 | if (base.substring(base.length-1) === "/") { 18 | // base ends with `/` 19 | return base + path; 20 | } 21 | return base + "/" + path; 22 | } 23 | 24 | function escapeHtml (value) { 25 | return value.replace(/&/g, '&') 26 | .replace(/"/g, '"') 27 | .replace(//g, '>'); 29 | } 30 | 31 | function formatResult (location, title, summary) { 32 | return '

'+ escapeHtml(title) + '

' + escapeHtml(summary) +'

'; 33 | } 34 | 35 | function displayResults (results) { 36 | var search_results = document.getElementById("mkdocs-search-results"); 37 | while (search_results.firstChild) { 38 | search_results.removeChild(search_results.firstChild); 39 | } 40 | if (results.length > 0){ 41 | for (var i=0; i < results.length; i++){ 42 | var result = results[i]; 43 | var html = formatResult(result.location, result.title, result.summary); 44 | search_results.insertAdjacentHTML('beforeend', html); 45 | } 46 | } else { 47 | var noResultsText = search_results.getAttribute('data-no-results-text'); 48 | if (!noResultsText) { 49 | noResultsText = "No results found"; 50 | } 51 | search_results.insertAdjacentHTML('beforeend', '

' + noResultsText + '

'); 52 | } 53 | } 54 | 55 | function doSearch () { 56 | var query = document.getElementById('mkdocs-search-query').value; 57 | if (query.length > min_search_length) { 58 | if (!window.Worker) { 59 | displayResults(search(query)); 60 | } else { 61 | searchWorker.postMessage({query: query}); 62 | } 63 | } else { 64 | // Clear results for short queries 65 | displayResults([]); 66 | } 67 | } 68 | 69 | function initSearch () { 70 | var search_input = document.getElementById('mkdocs-search-query'); 71 | if (search_input) { 72 | search_input.addEventListener("keyup", doSearch); 73 | } 74 | var term = getSearchTermFromLocation(); 75 | if (term) { 76 | search_input.value = term; 77 | doSearch(); 78 | } 79 | } 80 | 81 | function onWorkerMessage (e) { 82 | if (e.data.allowSearch) { 83 | initSearch(); 84 | } else if (e.data.results) { 85 | var results = e.data.results; 86 | displayResults(results); 87 | } else if (e.data.config) { 88 | min_search_length = e.data.config.min_search_length-1; 89 | } 90 | } 91 | 92 | if (!window.Worker) { 93 | console.log('Web Worker API not supported'); 94 | // load index in main thread 95 | $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { 96 | console.log('Loaded worker'); 97 | init(); 98 | window.postMessage = function (msg) { 99 | onWorkerMessage({data: msg}); 100 | }; 101 | }).fail(function (jqxhr, settings, exception) { 102 | console.error('Could not load worker.js'); 103 | }); 104 | } else { 105 | // Wrap search in a web worker 106 | var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); 107 | searchWorker.postMessage({init: true}); 108 | searchWorker.onmessage = onWorkerMessage; 109 | } 110 | -------------------------------------------------------------------------------- /search/worker.js: -------------------------------------------------------------------------------- 1 | var base_path = 'function' === typeof importScripts ? '.' : '/search/'; 2 | var allowSearch = false; 3 | var index; 4 | var documents = {}; 5 | var lang = ['en']; 6 | var data; 7 | 8 | function getScript(script, callback) { 9 | console.log('Loading script: ' + script); 10 | $.getScript(base_path + script).done(function () { 11 | callback(); 12 | }).fail(function (jqxhr, settings, exception) { 13 | console.log('Error: ' + exception); 14 | }); 15 | } 16 | 17 | function getScriptsInOrder(scripts, callback) { 18 | if (scripts.length === 0) { 19 | callback(); 20 | return; 21 | } 22 | getScript(scripts[0], function() { 23 | getScriptsInOrder(scripts.slice(1), callback); 24 | }); 25 | } 26 | 27 | function loadScripts(urls, callback) { 28 | if( 'function' === typeof importScripts ) { 29 | importScripts.apply(null, urls); 30 | callback(); 31 | } else { 32 | getScriptsInOrder(urls, callback); 33 | } 34 | } 35 | 36 | function onJSONLoaded () { 37 | data = JSON.parse(this.responseText); 38 | var scriptsToLoad = ['lunr.js']; 39 | if (data.config && data.config.lang && data.config.lang.length) { 40 | lang = data.config.lang; 41 | } 42 | if (lang.length > 1 || lang[0] !== "en") { 43 | scriptsToLoad.push('lunr.stemmer.support.js'); 44 | if (lang.length > 1) { 45 | scriptsToLoad.push('lunr.multi.js'); 46 | } 47 | if (lang.includes("ja") || lang.includes("jp")) { 48 | scriptsToLoad.push('tinyseg.js'); 49 | } 50 | for (var i=0; i < lang.length; i++) { 51 | if (lang[i] != 'en') { 52 | scriptsToLoad.push(['lunr', lang[i], 'js'].join('.')); 53 | } 54 | } 55 | } 56 | loadScripts(scriptsToLoad, onScriptsLoaded); 57 | } 58 | 59 | function onScriptsLoaded () { 60 | console.log('All search scripts loaded, building Lunr index...'); 61 | if (data.config && data.config.separator && data.config.separator.length) { 62 | lunr.tokenizer.separator = new RegExp(data.config.separator); 63 | } 64 | 65 | if (data.index) { 66 | index = lunr.Index.load(data.index); 67 | data.docs.forEach(function (doc) { 68 | documents[doc.location] = doc; 69 | }); 70 | console.log('Lunr pre-built index loaded, search ready'); 71 | } else { 72 | index = lunr(function () { 73 | if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) { 74 | this.use(lunr[lang[0]]); 75 | } else if (lang.length > 1) { 76 | this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility 77 | } 78 | this.field('title'); 79 | this.field('text'); 80 | this.ref('location'); 81 | 82 | for (var i=0; i < data.docs.length; i++) { 83 | var doc = data.docs[i]; 84 | this.add(doc); 85 | documents[doc.location] = doc; 86 | } 87 | }); 88 | console.log('Lunr index built, search ready'); 89 | } 90 | allowSearch = true; 91 | postMessage({config: data.config}); 92 | postMessage({allowSearch: allowSearch}); 93 | } 94 | 95 | function init () { 96 | var oReq = new XMLHttpRequest(); 97 | oReq.addEventListener("load", onJSONLoaded); 98 | var index_path = base_path + '/search_index.json'; 99 | if( 'function' === typeof importScripts ){ 100 | index_path = 'search_index.json'; 101 | } 102 | oReq.open("GET", index_path); 103 | oReq.send(); 104 | } 105 | 106 | function search (query) { 107 | if (!allowSearch) { 108 | console.error('Assets for search still loading'); 109 | return; 110 | } 111 | 112 | var resultDocuments = []; 113 | var results = index.search(query); 114 | for (var i=0; i < results.length; i++){ 115 | var result = results[i]; 116 | doc = documents[result.ref]; 117 | doc.summary = doc.text.substring(0, 200); 118 | resultDocuments.push(doc); 119 | } 120 | return resultDocuments; 121 | } 122 | 123 | if( 'function' === typeof importScripts ) { 124 | onmessage = function (e) { 125 | if (e.data.init) { 126 | init(); 127 | } else if (e.data.query) { 128 | postMessage({ results: search(e.data.query) }); 129 | } else { 130 | console.error("Worker - Unrecognized message: " + e); 131 | } 132 | }; 133 | } 134 | -------------------------------------------------------------------------------- /sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /sitemap.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/sitemap.xml.gz -------------------------------------------------------------------------------- /webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UnidayStudio/CaveEngine-Docs/927dfacf795efc1b5c800e0e5f23f0cc2db852bc/webfonts/fa-v4compatibility.woff2 --------------------------------------------------------------------------------