├── .gitattributes ├── .gitignore ├── CHANGELOG.txt ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── models │ ├── Untitled.png │ ├── blobby.mtl │ ├── blobby.obj │ ├── cornell_box.mtl │ ├── cornell_box.obj │ ├── cornell_box2.mtl │ ├── cube.mtl │ ├── cube.obj │ ├── directions_cube.png │ ├── gurp.blend │ ├── gurp.ogex │ ├── helper-cube.blend │ ├── helper-cube.blend1 │ ├── helper-cube.mtl │ ├── helper-cube.obj │ ├── lego.obj │ ├── plane.mtl │ ├── plane.obj │ ├── plane.png │ ├── pship.mtl │ ├── pship.obj │ ├── quad.obj │ ├── teapot.obj │ ├── textured_thing.mtl │ ├── textured_thing.obj │ └── textured_thing.png └── shaders │ ├── fs.glsl │ └── vs.glsl ├── b ├── build.rs ├── clean ├── game_state ├── Cargo.lock ├── Cargo.toml ├── README.md ├── benches │ └── node.rs ├── build.rs ├── examples │ └── nodes.rs ├── src │ ├── event.rs │ ├── input │ │ ├── events.rs │ │ ├── mod.rs │ │ └── screen.rs │ ├── lib.rs │ ├── model.rs │ ├── state │ │ ├── access.rs │ │ ├── asset_state.rs │ │ ├── input_state.rs │ │ ├── mod.rs │ │ ├── render_state.rs │ │ ├── simulation_state.rs │ │ └── ui_state.rs │ ├── thing │ │ └── mod.rs │ ├── tree.rs │ ├── ui │ │ ├── events.rs │ │ ├── mod.rs │ │ └── view.rs │ └── utils │ │ ├── fps.rs │ │ └── mod.rs └── tests │ └── node.rs ├── mod_asset_loader ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── mod_dummy ├── Cargo.lock ├── Cargo.toml ├── README.md ├── build.rs └── src │ └── lib.rs ├── mod_gamepad ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── mod_input ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── mod_rendering_opengl ├── Cargo.lock ├── Cargo.toml ├── README.md └── src │ ├── lib.rs │ └── renderer │ ├── mod.rs │ └── opengl │ └── mod.rs ├── mod_rendering_vulkano ├── Cargo.lock ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── lib.rs │ └── renderer │ ├── mod.rs │ └── vulkano │ ├── mod.rs │ ├── vertex.rs │ └── vulkano_sdl2.rs ├── mod_simulation ├── Cargo.lock ├── Cargo.toml ├── README.md ├── build.rs └── src │ └── lib.rs ├── profile ├── rebuild-mods ├── run ├── src ├── lib.rs ├── libloader │ └── mod.rs └── main.rs └── todo.markdown /.gitattributes: -------------------------------------------------------------------------------- 1 | *text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.swo 3 | *.swp 4 | *.iml 5 | .idea/** 6 | **/.idea/** 7 | *.log 8 | **/massif* 9 | 10 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | # [workspace] 3 | # members = [ "mod_rendering_vulkano"] 4 | 5 | [package] 6 | name = "sg_engine" 7 | version = "0.2.0" 8 | authors = ["Daniel Werner "] 9 | publish = false 10 | build = "build.rs" 11 | edition = "2018" 12 | 13 | [lib] 14 | name = "engine" 15 | crate-type = ["rlib"] 16 | 17 | [dependencies] 18 | ansi_term = "0.12" 19 | libloading = "0.7" 20 | eyre = "0.6.5" 21 | 22 | [dependencies.game_state] 23 | path = "game_state" 24 | 25 | # TODO: explore this again, look at release strategies: 26 | # mods don't need to be deps, but can be 27 | # to get cargo to build them when the main project is built 28 | # this builds them and puts them in the target for the main output 29 | # mod_rendering = { path = "mod_rendering" } 30 | # mod_asset_loader = { path = "mod_asset_loader" } 31 | # mod_simulation = { path = "mod_simulation" } 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Daniel Werner 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SG Engine (toy engine) 2 | 3 | For now, this is just a toy engine, with many missing features, and breaks every 3 minutes. 4 | 5 | 6 | ### Demo 7 | IMAGE ALT TEXT HERE 8 | 9 | This project is intended to be my first stab at a complete game engine - but it is by no means complete yet. The main ideas around architecture are: 10 | 11 | - Modular system design - allowing hot code loading 12 | - composition over inheritance (but it's Rust so of course) 13 | 14 | ## What works: 15 | - Module runtime reloading 16 | - Vulkan rendering using [vulkano](https://github.com/tomaka/vulkano) 17 | - Scene graph (Rc-based ADG) and push-constants 18 | - Loading obj models using [nom-obj](https://github.com/dwerner/nom-obj) 19 | - Diffuse textures, UVW coordinates 20 | 21 | ## To do: 22 | - Multiple textures 23 | - Extremely inefficient shaders (per-vertex matrix operations, for no good reason) 24 | - pretty much anything else... 25 | 26 | As I said, this is very much a work in progress, but I'd love input or PRs or criticism. 27 | 28 | ## My *opinionated architecture 29 | 30 | *We all have our opinions. :) 31 | 32 | ## Hot loading 33 | 34 | For any project that I work on, I like to move quickly and try ideas fast. I'm a monkey coder; I bash on this part and that until I get things to work. I don't want to wait for a full-compile cycle to try out a new idea... So a lot of my effort is spent in this library to optimize for that case. One way to do this is to reload sections of the program at runtime. 35 | 36 | Credits for inspiration: 37 | 38 | - [null program](http://nullprogram.com/blog/2014/12/23/) 39 | - [handmade hero](https://handmadehero.org/) 40 | 41 | 42 | ## `game_state` 43 | 44 | The system is comprised of a base library for shared state, in addition to modules. `game_state` defines all shared, base types in the system, including the most global `State`, but also shared types and traits defining behavior and structure of input, ui, events, rendering, world entities, etc. 45 | 46 | The `State` struct is central to the design, as it represents the state the game passes between each module. This allows each module, when not operating on the state, to be reloaded and the old state they are responsible for to be cleared. The actual loading of the modules is handled in the main project under `src/libloading`. 47 | 48 | ## Access traits 49 | 50 | Several traits are defined and implemented on `State` to serve as a window of responsibility for common operations on the `State` object itself. This decouples the modules from any exact internal structure of `State`, but also allows common functionality to be shared between access traits. At a higher level, access traits to `State` serve as a way for a mod to state which aspects of `State` it really wants access to. 51 | 52 | ## Modules 53 | 54 | Modules are compiled rust code, but are loaded at runtime and can be modified during the course of execution. When a new version is built, it will be picked up by `libloading` and loaded, while the old library will be unloaded. 55 | 56 | In contrast, any changes to the `game_state` crate or it's dependencies (`nom-obj` - an .obj model parser, for instance) will need everything to be rebuilt that depends on it, otherwise strange things may happen, or worse. 57 | 58 | ### `mod_dummy` 59 | 60 | This is a template mod, and is not built or linked, but rather serves as a starting point for creating a new mod. 61 | 62 | ### `mod_asset_loader` 63 | 64 | A simple mod intended to load assets and prepare them for use by attaching them to the `State` object. 65 | 66 | Access traits used: `RenderLayerAccess` 67 | 68 | TODO: 69 | - Expand on asset loading strategy 70 | 71 | ### `mod_input` 72 | 73 | This module is responsible for coordinating and gathering input events in the internal format described in 74 | `game_state::input`. 75 | 76 | Access traits used: `InputAccess` 77 | 78 | TODO: 79 | - Gather input from joysticks 80 | - ... 81 | 82 | ### `mod_rendering_x` 83 | 84 | Responsible for the implementation of renderers, adding the capacity for orthogonal changes to each renderer at runtime. Of course the renderers need to know how to clean themselves up in addition to initialize. 85 | 86 | Renderer Status: 87 | 88 | - VulkanRenderer - model and texture loading, needs work to expand asset pipeline support 89 | - OpenGLRenderer - Stubbed, little more 90 | 91 | Access Traits Used: 92 | - `RenderAccess` 93 | - `RenderLayerAccess` 94 | 95 | TODO: 96 | - Implement OpenGL renderer so this can run on any machine supporting OpenGL 97 | - Renderer specific, but lots of work needs to be done here, probably dependent on `mod_asset_loader` and expansion of access traits 98 | - Software renderer 99 | 100 | ### `mod_simulation` 101 | 102 | Simulation of the game world itself. 103 | 104 | Access Traits Used: `SimulationAccess` 105 | 106 | Todo: 107 | - everything - this mod is just stubbed at this point 108 | 109 | 110 | # Building on linux 111 | ## Dependencies: 112 | - libudev-dev 113 | - libsdl2-dev 114 | - python-is-python3 115 | 116 | ## Environment 117 | You may have to set 118 | ``` 119 | export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json 120 | ``` 121 | Or similar, depending on your device. -------------------------------------------------------------------------------- /assets/models/Untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/Untitled.png -------------------------------------------------------------------------------- /assets/models/blobby.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'blobby.blend' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 0.000000 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.800000 0.800000 0.800000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | -------------------------------------------------------------------------------- /assets/models/cornell_box.mtl: -------------------------------------------------------------------------------- 1 | newmtl white 2 | Ka 0 0 0 3 | Kd 1 1 1 4 | Ks 0 0 0 5 | 6 | newmtl red 7 | Ka 0 0 0 8 | Kd 1 0 0 9 | Ks 0 0 0 10 | 11 | -------------------------------------------------------------------------------- /assets/models/cornell_box.obj: -------------------------------------------------------------------------------- 1 | # cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project. 2 | # original cornell box data 3 | # comment 4 | 5 | # empty line including some space 6 | 7 | 8 | mtllib cornell_box.mtl 9 | mtllib cornell_box2.mtl 10 | 11 | o floor 12 | usemtl white 13 | v 552.8 0.0 0.0 14 | v 0.0 0.0 0.0 15 | v 0.0 0.0 559.2 16 | v 549.6 0.0 559.2 17 | 18 | v 130.0 0.0 65.0 19 | v 82.0 0.0 225.0 20 | v 240.0 0.0 272.0 21 | v 290.0 0.0 114.0 22 | 23 | v 423.0 0.0 247.0 24 | v 265.0 0.0 296.0 25 | v 314.0 0.0 456.0 26 | v 472.0 0.0 406.0 27 | 28 | f 1 2 3 4 29 | f 8 7 6 5 30 | f 12 11 10 9 31 | 32 | o light 33 | usemtl light 34 | v 343.0 548.0 227.0 35 | v 343.0 548.0 332.0 36 | v 213.0 548.0 332.0 37 | v 213.0 548.0 227.0 38 | f -4 -3 -2 -1 39 | 40 | o ceiling 41 | usemtl white 42 | v 556.0 548.8 0.0 43 | v 556.0 548.8 559.2 44 | v 0.0 548.8 559.2 45 | v 0.0 548.8 0.0 46 | f -4 -3 -2 -1 47 | 48 | o back_wall 49 | usemtl white 50 | v 549.6 0.0 559.2 51 | v 0.0 0.0 559.2 52 | v 0.0 548.8 559.2 53 | v 556.0 548.8 559.2 54 | f -4 -3 -2 -1 55 | 56 | o front_wall 57 | usemtl blue 58 | v 549.6 0.0 0 59 | v 0.0 0.0 0 60 | v 0.0 548.8 0 61 | v 556.0 548.8 0 62 | #f -1 -2 -3 -4 63 | 64 | o green_wall 65 | usemtl green 66 | v 0.0 0.0 559.2 67 | v 0.0 0.0 0.0 68 | v 0.0 548.8 0.0 69 | v 0.0 548.8 559.2 70 | f -4 -3 -2 -1 71 | 72 | o red_wall 73 | usemtl red 74 | v 552.8 0.0 0.0 75 | v 549.6 0.0 559.2 76 | v 556.0 548.8 559.2 77 | v 556.0 548.8 0.0 78 | f -4 -3 -2 -1 79 | 80 | o short_block 81 | usemtl white 82 | 83 | v 130.0 165.0 65.0 84 | v 82.0 165.0 225.0 85 | v 240.0 165.0 272.0 86 | v 290.0 165.0 114.0 87 | f -4 -3 -2 -1 88 | 89 | v 290.0 0.0 114.0 90 | v 290.0 165.0 114.0 91 | v 240.0 165.0 272.0 92 | v 240.0 0.0 272.0 93 | f -4 -3 -2 -1 94 | 95 | v 130.0 0.0 65.0 96 | v 130.0 165.0 65.0 97 | v 290.0 165.0 114.0 98 | v 290.0 0.0 114.0 99 | f -4 -3 -2 -1 100 | 101 | v 82.0 0.0 225.0 102 | v 82.0 165.0 225.0 103 | v 130.0 165.0 65.0 104 | v 130.0 0.0 65.0 105 | f -4 -3 -2 -1 106 | 107 | v 240.0 0.0 272.0 108 | v 240.0 165.0 272.0 109 | v 82.0 165.0 225.0 110 | v 82.0 0.0 225.0 111 | f -4 -3 -2 -1 112 | 113 | o tall_block 114 | usemtl white 115 | 116 | v 423.0 330.0 247.0 117 | v 265.0 330.0 296.0 118 | v 314.0 330.0 456.0 119 | v 472.0 330.0 406.0 120 | f -4 -3 -2 -1 121 | 122 | usemtl white 123 | v 423.0 0.0 247.0 124 | v 423.0 330.0 247.0 125 | v 472.0 330.0 406.0 126 | v 472.0 0.0 406.0 127 | f -4 -3 -2 -1 128 | 129 | v 472.0 0.0 406.0 130 | v 472.0 330.0 406.0 131 | v 314.0 330.0 456.0 132 | v 314.0 0.0 456.0 133 | f -4 -3 -2 -1 134 | 135 | v 314.0 0.0 456.0 136 | v 314.0 330.0 456.0 137 | v 265.0 330.0 296.0 138 | v 265.0 0.0 296.0 139 | f -4 -3 -2 -1 140 | 141 | v 265.0 0.0 296.0 142 | v 265.0 330.0 296.0 143 | v 423.0 330.0 247.0 144 | v 423.0 0.0 247.0 145 | f -4 -3 -2 -1 146 | 147 | -------------------------------------------------------------------------------- /assets/models/cornell_box2.mtl: -------------------------------------------------------------------------------- 1 | newmtl blue 2 | Ka 0 0 0 3 | Kd 0 0 1 4 | Ks 0 0 0 5 | Ns 10 6 | crazy_unknown Wierd stuff here 7 | 8 | newmtl light 9 | Ka 20 20 20 10 | Kd 1 1 1 11 | Ks 0 0 0 12 | d 0.8 13 | 14 | newmtl green 15 | Ka 0 0 0 16 | Kd 0 1 0 17 | Ks 0 0 0 18 | map_Ka dummy_texture.png 19 | map_Kd dummy_texture.png 20 | map_Ks dummy_texture.png 21 | map_Ns dummy_texture.png 22 | map_d dummy_texture.png 23 | 24 | -------------------------------------------------------------------------------- /assets/models/cube.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 0 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | map_Kd Untitled.png 12 | -------------------------------------------------------------------------------- /assets/models/cube.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.78 (sub 0) OBJ File: 'untitled.blend' 2 | # www.blender.org 3 | mtllib cube.mtl 4 | o Cube_Cube.001 5 | v -1.000000 -1.000000 1.000000 6 | v -1.000000 1.000000 1.000000 7 | v -1.000000 -1.000000 -1.000000 8 | v -1.000000 1.000000 -1.000000 9 | v 1.000000 -1.000000 1.000000 10 | v 1.000000 1.000000 1.000000 11 | v 1.000000 -1.000000 -1.000000 12 | v 1.000000 1.000000 -1.000000 13 | vt 0.0000 0.0000 14 | vt 1.0000 0.0000 15 | vt 1.0000 1.0000 16 | vt 0.0000 0.0000 17 | vt 1.0000 0.0000 18 | vt 1.0000 1.0000 19 | vt 0.0000 0.0000 20 | vt 1.0000 0.0000 21 | vt 1.0000 1.0000 22 | vt 0.0000 0.0000 23 | vt 1.0000 0.0000 24 | vt 1.0000 1.0000 25 | vt 0.0000 0.0000 26 | vt 1.0000 0.0000 27 | vt 1.0000 1.0000 28 | vt 1.0000 0.0000 29 | vt 1.0000 0.0000 30 | vt 1.0000 0.0000 31 | vt 1.0000 1.0000 32 | vn -1.0000 0.0000 0.0000 33 | vn 0.0000 0.0000 -1.0000 34 | vn 1.0000 0.0000 0.0000 35 | vn 0.0000 0.0000 1.0000 36 | vn 0.0000 -1.0000 0.0000 37 | vn 0.0000 1.0000 0.0000 38 | usemtl None 39 | s off 40 | f 2/1/1 3/2/1 1/3/1 41 | f 4/4/2 7/5/2 3/6/2 42 | f 8/7/3 5/8/3 7/9/3 43 | f 6/10/4 1/11/4 5/12/4 44 | f 7/13/5 1/11/5 3/6/5 45 | f 4/4/6 6/14/6 8/15/6 46 | f 2/1/1 4/16/1 3/6/1 47 | f 4/4/2 8/17/2 7/9/2 48 | f 8/7/3 6/14/3 5/12/3 49 | f 6/10/4 2/18/4 1/3/4 50 | f 7/13/5 5/8/5 1/3/5 51 | f 4/4/6 2/18/6 6/19/6 52 | -------------------------------------------------------------------------------- /assets/models/directions_cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/directions_cube.png -------------------------------------------------------------------------------- /assets/models/gurp.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/gurp.blend -------------------------------------------------------------------------------- /assets/models/helper-cube.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/helper-cube.blend -------------------------------------------------------------------------------- /assets/models/helper-cube.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/helper-cube.blend1 -------------------------------------------------------------------------------- /assets/models/helper-cube.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'helper-cube.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material.001 5 | Ns 323.999994 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.0 0.0 0.0 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd directions_cube.png 14 | -------------------------------------------------------------------------------- /assets/models/helper-cube.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.80 (sub 75) OBJ File: 'helper-cube.blend' 2 | # www.blender.org 3 | mtllib helper-cube.mtl 4 | o Cube 5 | v -1.000000 -1.000000 1.000000 6 | v 1.000000 -1.000000 1.000000 7 | v -1.000000 -1.000000 -1.000000 8 | v 1.000000 -1.000000 -1.000000 9 | v -1.000000 1.000000 1.000000 10 | v 1.000000 1.000000 1.000000 11 | v -1.000000 1.000000 -1.000000 12 | v 1.000000 1.000000 -1.000000 13 | v -2.413369 -1.000000 -1.000000 14 | v -2.413369 1.000000 -1.000000 15 | v -2.413369 -1.000000 1.000000 16 | v -2.413369 1.000000 1.000000 17 | v 1.000000 1.000000 -3.004010 18 | v -1.000000 1.000000 -3.004010 19 | v -1.000000 -1.000000 -3.004010 20 | v 1.000000 -1.000000 -3.004010 21 | v -1.000000 -2.935748 1.000000 22 | v 1.000000 -2.935748 1.000000 23 | v -1.000000 -2.935748 -1.000000 24 | v 1.000000 -2.935748 -1.000000 25 | vt 0.245995 0.739057 26 | vt 0.194612 0.702864 27 | vt 0.228207 0.673344 28 | vt 0.432156 0.442442 29 | vt 0.495113 0.497350 30 | vt 0.435410 0.484259 31 | vt 0.747832 0.498220 32 | vt 0.499600 0.746809 33 | vt 0.500740 0.498783 34 | vt 0.498711 0.498555 35 | vt 0.248545 0.247699 36 | vt 0.494135 0.246814 37 | vt 0.998369 0.568702 38 | vt 0.942981 0.514603 39 | vt 0.992753 0.506970 40 | vt 0.996905 0.500643 41 | vt 0.751911 0.749516 42 | vt 0.752254 0.498233 43 | vt 0.672703 0.569345 44 | vt 0.743613 0.512808 45 | vt 0.737523 0.563977 46 | vt 0.760087 0.741046 47 | vt 0.831673 0.689647 48 | vt 0.758274 0.687044 49 | vt 0.751905 0.746040 50 | vt 0.249908 0.498991 51 | vt 0.302520 0.507020 52 | vt 0.262557 0.559443 53 | vt 0.256020 0.513514 54 | vt 0.997433 0.750607 55 | vt 0.247925 0.753917 56 | vt 0.498867 1.004300 57 | vt 0.254044 1.001703 58 | vt 0.495891 0.752830 59 | vt 0.986019 0.692875 60 | vt 0.943174 0.745725 61 | vt 0.985203 0.749033 62 | vt 0.450842 0.541830 63 | vt 0.491597 0.512277 64 | vt 0.489289 0.548978 65 | vt 0.500546 0.501033 66 | vt 0.248426 0.749538 67 | vt 0.250890 0.499443 68 | vt 0.499444 0.750831 69 | vt 0.489289 0.991531 70 | vt 0.449069 0.947168 71 | vt 0.493906 0.942937 72 | vt 0.172330 0.562473 73 | vt 0.243781 0.506312 74 | vt 0.239431 0.562172 75 | vt 0.248984 0.499269 76 | vt -0.000578 0.747573 77 | vt -0.002150 0.498375 78 | vt 0.250623 0.749344 79 | vt 0.255384 0.261464 80 | vt 0.316859 0.312335 81 | vt 0.262124 0.314012 82 | vt 0.703745 0.744783 83 | vt 0.735664 0.702233 84 | vt 0.706088 0.697731 85 | vt 0.181539 0.750972 86 | vt 0.484204 0.433297 87 | vt 0.941285 0.555479 88 | vt 0.693174 0.505491 89 | vt 0.821215 0.745672 90 | vt 0.303797 0.559507 91 | vt 0.947525 0.701587 92 | vt 0.452931 0.512267 93 | vt 0.451338 0.987106 94 | vt 0.174250 0.504208 95 | vt 0.313246 0.255838 96 | vt 0.734878 0.742202 97 | vn 0.0000 1.0000 0.0000 98 | vn -1.0000 0.0000 0.0000 99 | vn 0.0000 -1.0000 0.0000 100 | vn 0.0000 0.0000 -1.0000 101 | vn 0.0000 0.0000 1.0000 102 | vn 1.0000 0.0000 0.0000 103 | usemtl Material.001 104 | s off 105 | f 3/1/1 11/2/1 1/3/1 106 | f 8/4/2 16/5/2 4/6/2 107 | f 6/7/3 7/8/3 8/9/3 108 | f 8/10/2 2/11/2 6/12/2 109 | f 2/13/4 17/14/4 1/15/4 110 | f 2/16/4 5/17/4 6/18/4 111 | f 5/19/3 10/20/3 7/21/3 112 | f 7/22/3 13/23/3 8/24/3 113 | f 6/7/3 5/25/3 7/8/3 114 | f 8/10/2 4/26/2 2/11/2 115 | f 3/27/5 20/28/5 4/29/5 116 | f 2/16/4 1/30/4 5/17/4 117 | f 9/31/6 12/32/6 11/33/6 118 | f 9/31/6 10/34/6 12/32/6 119 | f 1/35/4 12/36/4 5/37/4 120 | f 7/38/5 9/39/5 3/40/5 121 | f 13/41/5 15/42/5 16/43/5 122 | f 13/41/5 14/44/5 15/42/5 123 | f 3/45/6 14/46/6 7/47/6 124 | f 4/48/1 15/49/1 3/50/1 125 | f 20/51/1 17/52/1 18/53/1 126 | f 20/51/1 19/54/1 17/52/1 127 | f 4/55/2 18/56/2 2/57/2 128 | f 1/58/6 19/59/6 3/60/6 129 | f 3/1/1 9/61/1 11/2/1 130 | f 8/4/2 13/62/2 16/5/2 131 | f 2/13/4 18/63/4 17/14/4 132 | f 5/19/3 12/64/3 10/20/3 133 | f 7/22/3 14/65/3 13/23/3 134 | f 3/27/5 19/66/5 20/28/5 135 | f 1/35/4 11/67/4 12/36/4 136 | f 7/38/5 10/68/5 9/39/5 137 | f 3/45/6 15/69/6 14/46/6 138 | f 4/48/1 16/70/1 15/49/1 139 | f 4/55/2 20/71/2 18/56/2 140 | f 1/58/6 17/72/6 19/59/6 141 | -------------------------------------------------------------------------------- /assets/models/lego.obj: -------------------------------------------------------------------------------- 1 | g Group0 2 | o lego 3 | v 1000.000000 -505.434990 -505.434990 4 | vn 0.577350 -0.577350 -0.577350 5 | v 1000.000000 505.434990 -505.434990 6 | vn 0.333333 0.666667 -0.666667 7 | v -1000.000000 505.434990 -505.434990 8 | vn -0.333333 0.666667 -0.666667 9 | v 510.856986 -505.434990 -505.434990 10 | vn -0.577350 -0.577350 -0.577350 11 | v 510.856986 -255.427986 -505.434990 12 | vn -0.800000 0.000000 -0.600000 13 | v 510.856986 -5.437000 -505.434990 14 | vn -0.235702 -0.235702 -0.942809 15 | v -244.555995 -5.437000 -505.434990 16 | vn 0.000000 -0.707107 -0.707107 17 | v -1000.000000 -5.437000 -505.434990 18 | vn -0.577350 -0.577350 -0.577350 19 | v -1000.000000 249.999002 -505.434990 20 | vn -0.894427 0.000000 -0.447214 21 | v 0.015000 505.434990 -505.434990 22 | vn 0.000000 0.707107 -0.707107 23 | v 1000.000000 -0.008000 -505.434990 24 | vn 0.780869 0.000000 -0.624695 25 | v 755.428016 -505.434990 -505.434990 26 | vn 0.000000 -0.707107 -0.707107 27 | v 1000.000000 505.434990 505.434990 28 | vn 0.577350 0.577350 0.577350 29 | v 510.856986 -0.008000 505.434990 30 | vn -0.577350 -0.577350 0.577350 31 | v 1000.000000 -0.008000 505.434990 32 | vn 0.577350 -0.577350 0.577350 33 | v 755.428016 -0.008000 505.434990 34 | vn 0.000000 -0.707107 0.707107 35 | v 510.856986 252.714008 505.434990 36 | vn -0.600000 0.000000 0.800000 37 | v 510.856986 505.434990 505.434990 38 | vn -0.577350 0.577350 0.577350 39 | v 755.428016 505.434990 505.434990 40 | vn 0.000000 0.707107 0.707107 41 | v 1000.000000 252.714008 505.434990 42 | vn 0.600000 0.000000 0.800000 43 | v 510.856986 -0.008000 1.211000 44 | vn -0.904534 -0.301511 0.301511 45 | v 1000.000000 -505.434990 1.211000 46 | vn 0.577350 -0.577350 0.577350 47 | v 1000.000000 -0.008000 1.211000 48 | vn 0.904534 -0.301511 0.301511 49 | v 510.856986 -505.434990 1.211000 50 | vn -0.816497 -0.408248 0.408248 51 | v 1000.000000 -0.008000 253.315002 52 | vn 0.600000 -0.800000 0.000000 53 | v 755.428016 -505.434990 1.211000 54 | vn 0.000000 -0.800000 0.600000 55 | v 510.856986 -505.434990 -255.427986 56 | vn -0.600000 -0.800000 0.000000 57 | v 510.856986 -505.434990 -5.437000 58 | vn -0.707107 -0.707107 0.000000 59 | v 1000.000000 -505.434990 -252.112001 60 | vn 0.600000 -0.800000 0.000000 61 | v 755.428016 -0.008000 1.211000 62 | vn 0.000000 -0.707107 0.707107 63 | v -1000.000000 -5.437000 -5.437000 64 | vn -0.577350 -0.577350 0.577350 65 | v 510.856986 505.434990 -5.437000 66 | vn -0.617213 0.771517 0.154303 67 | v 1000.000000 505.434990 -0.008000 68 | vn 0.857493 0.514496 0.000000 69 | v -1000.000000 505.434990 -5.437000 70 | vn -0.577350 0.577350 0.577350 71 | v -1000.000000 249.999002 -5.437000 72 | vn -0.800000 0.000000 0.600000 73 | v -1000.000000 -5.437000 -255.427986 74 | vn -0.707107 -0.707107 0.000000 75 | v -1000.000000 505.434990 -255.427986 76 | vn -0.832050 0.554700 0.000000 77 | v 1000.000000 -252.714008 1.211000 78 | vn 0.600000 0.000000 0.800000 79 | v -244.555995 505.434990 -5.437000 80 | vn 0.000000 0.707107 0.707107 81 | v -244.555995 -5.437000 -5.437000 82 | vn 0.000000 -0.800000 0.600000 83 | v 510.856986 -252.714008 1.211000 84 | vn -0.600000 0.000000 0.800000 85 | v 510.856986 -5.437000 -5.437000 86 | vn -0.872872 -0.218218 0.436436 87 | v 510.856986 -0.008000 253.315002 88 | vn -0.600000 -0.800000 0.000000 89 | v 510.856986 -255.427986 -5.437000 90 | vn -1.000000 0.000000 0.000000 91 | v 510.856986 -5.437000 -255.427986 92 | vn -0.707107 -0.707107 0.000000 93 | f 4//4 5//5 12//12 94 | f 5//5 6//6 11//11 95 | f 6//6 7//7 10//10 96 | f 7//7 8//8 9//9 97 | f 9//9 3//3 7//7 98 | f 3//3 10//10 7//7 99 | f 10//10 2//2 6//6 100 | f 2//2 11//11 6//6 101 | f 11//11 1//1 12//12 102 | f 12//12 5//5 11//11 103 | f 15//15 20//20 16//16 104 | f 16//16 17//17 14//14 105 | f 17//17 19//19 18//18 106 | f 19//19 20//20 13//13 107 | f 20//20 17//17 16//16 108 | f 17//17 20//20 19//19 109 | f 1//1 29//29 12//12 110 | f 12//12 27//27 4//4 111 | f 24//24 28//28 26//26 112 | f 26//26 29//29 22//22 113 | f 27//27 26//26 28//28 114 | f 29//29 27//27 12//12 115 | f 26//26 27//27 29//29 116 | f 8//8 36//36 9//9 117 | f 9//9 37//37 3//3 118 | f 34//34 37//37 35//35 119 | f 35//35 36//36 31//31 120 | f 36//36 35//35 9//9 121 | f 9//9 35//35 37//37 122 | f 3//3 39//39 10//10 123 | f 10//10 32//32 2//2 124 | f 13//13 33//33 19//19 125 | f 19//19 32//32 18//18 126 | f 34//34 39//39 37//37 127 | f 37//37 39//39 3//3 128 | f 32//32 10//10 39//39 129 | f 2//2 32//32 33//33 130 | f 33//33 32//32 19//19 131 | f 2//2 33//33 11//11 132 | f 11//11 29//29 1//1 133 | f 15//15 25//25 20//20 134 | f 20//20 33//33 13//13 135 | f 22//22 29//29 38//38 136 | f 38//38 11//11 23//23 137 | f 23//23 33//33 25//25 138 | f 33//33 23//23 11//11 139 | f 11//11 38//38 29//29 140 | f 25//25 33//33 20//20 141 | f 6//6 5//5 45//45 142 | f 5//5 4//4 27//27 143 | f 27//27 28//28 44//44 144 | f 44//44 42//42 45//45 145 | f 45//45 5//5 44//44 146 | f 5//5 27//27 44//44 147 | f 8//8 7//7 36//36 148 | f 7//7 6//6 45//45 149 | f 31//31 36//36 40//40 150 | f 42//42 40//40 45//45 151 | f 36//36 7//7 40//40 152 | f 7//7 45//45 40//40 153 | f 31//31 40//40 35//35 154 | f 35//35 39//39 34//34 155 | f 39//39 42//42 32//32 156 | f 42//42 39//39 40//40 157 | f 40//40 39//39 35//35 158 | f 14//14 17//17 43//43 159 | f 17//17 18//18 32//32 160 | f 28//28 24//24 44//44 161 | f 42//42 44//44 41//41 162 | f 32//32 42//42 21//21 163 | f 24//24 41//41 44//44 164 | f 41//41 21//21 42//42 165 | f 21//21 43//43 32//32 166 | f 43//43 17//17 32//32 167 | f 22//22 38//38 26//26 168 | f 26//26 41//41 24//24 169 | f 23//23 30//30 38//38 170 | f 41//41 30//30 21//21 171 | f 38//38 41//41 26//26 172 | f 30//30 41//41 38//38 173 | f 15//15 16//16 25//25 174 | f 16//16 14//14 43//43 175 | f 23//23 25//25 30//30 176 | f 43//43 21//21 30//30 177 | f 25//25 16//16 43//43 178 | f 30//30 25//25 43//43 179 | -------------------------------------------------------------------------------- /assets/models/plane.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl Material 5 | Ns 323.999994 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.800000 0.800000 0.800000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.0 0.0 0.0 10 | Ni 1.450000 11 | d 1.000000 12 | illum 2 13 | map_Kd plane.png 14 | -------------------------------------------------------------------------------- /assets/models/plane.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.80 (sub 75) OBJ File: '' 2 | # www.blender.org 3 | mtllib plane.mtl 4 | o Cube 5 | v -1.000000 0.000000 1.000000 6 | v 1.000000 0.000000 1.000000 7 | v -1.000000 0.000000 -1.000000 8 | v 1.000000 0.000000 -1.000000 9 | vt 0.000000 0.000000 10 | vt 1.000000 0.000000 11 | vt 1.000000 1.000000 12 | vt 0.000000 1.000000 13 | vn 0.0000 1.0000 0.0000 14 | usemtl Material 15 | s off 16 | f 3/1/1 2/2/1 1/3/1 17 | f 3/1/1 4/4/1 2/2/1 18 | -------------------------------------------------------------------------------- /assets/models/plane.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/plane.png -------------------------------------------------------------------------------- /assets/models/pship.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'pship.blend' 2 | # Material Count: 3 3 | 4 | newmtl Material.002 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd Untitled.png 14 | -------------------------------------------------------------------------------- /assets/models/quad.obj: -------------------------------------------------------------------------------- 1 | # All supported face formats coupled with triangle and quad faces for testing 2 | # Note: Mixing face formats within an object is not supported, eg. an object 3 | # should NOT contain faces like: 4 | # f 1 2 3 5 | # f 4/1 5/5 3/3 6 | o Quad 7 | v 0 1 0 8 | v 0 0 0 9 | v 1 0 0 10 | v 1 1 0 11 | vn 0 0 1 12 | vt 0 1 13 | vt 0 0 14 | vt 1 0 15 | vt 1 1 16 | 17 | f 1/1 2/2 3/3 18 | f 1/1 3/3 4/4 19 | 20 | o Quad_face 21 | f 1/1/1 2/2/1 3/3/1 4/4/1 22 | 23 | o Tri_v_vn 24 | f 1//1 2//1 3//1 25 | 26 | -------------------------------------------------------------------------------- /assets/models/textured_thing.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'playground2.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material.001 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | map_Kd textured_thing.png 14 | -------------------------------------------------------------------------------- /assets/models/textured_thing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwerner/sg-engine/d33d01a0eb69258e62d3902133c22148a4303223/assets/models/textured_thing.png -------------------------------------------------------------------------------- /assets/shaders/fs.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #extension GL_ARB_separate_shader_objects : enable 4 | #extension GL_ARB_shading_language_450pack : enable 5 | 6 | layout(set = 0, binding = 0) uniform sampler2D tex; 7 | 8 | layout(location = 0) in vec3 v_normal; 9 | layout(location = 1) in vec2 v_uv; 10 | 11 | layout(location = 0) out vec4 f_color; 12 | 13 | const vec3 LIGHT = vec3(0.5, 0.5, 0.5); 14 | 15 | void main() { 16 | float brightness = dot(normalize(v_normal), normalize(LIGHT)); 17 | vec3 dark_color = vec3(0.7, 0.7, 0.7); 18 | vec3 regular_color = vec3(1.0, 1.0, 1.0); 19 | 20 | f_color = texture(tex, v_uv);// * vec4(mix(dark_color, regular_color, brightness), 1.0); 21 | //f_color = vec4(1.0, 1.0, 1.0, 1.0); 22 | } 23 | -------------------------------------------------------------------------------- /assets/shaders/vs.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #extension GL_ARB_separate_shader_objects : enable 4 | #extension GL_ARB_shading_language_420pack : enable 5 | 6 | layout(location = 0) in vec3 position; 7 | layout(location = 1) in vec3 normal; 8 | layout(location = 2) in vec2 uv; 9 | 10 | layout(location = 0) out vec3 v_normal; 11 | layout(location = 1) out vec2 v_uv; 12 | 13 | layout(set = 0, binding = 1) uniform Data { 14 | mat4 proj; 15 | } uniforms; 16 | 17 | layout(push_constant) uniform PushConstants { 18 | mat4 model_mat; 19 | } push_constants; 20 | 21 | void main() { 22 | mat4 mat = push_constants.model_mat; 23 | v_normal = transpose(inverse(mat3(mat))) * normal; 24 | gl_Position = uniforms.proj * mat * vec4(position, 1.0); 25 | v_uv = uv; 26 | } 27 | -------------------------------------------------------------------------------- /b: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | LOGFILE="$PWD/build_mod_$1.log" 4 | MODULE=mod_$1 5 | echo "building (opts: $2) $MODULE, see $LOGFILE" 6 | if (cd $MODULE && cargo build $2 > $LOGFILE 2>&1) ; then 7 | echo building $MODULE succeeded 8 | exit 0 9 | else 10 | echo "FAILED building $MODULE" 11 | exit 1 12 | fi 13 | 14 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | // build.rs 2 | use std::env; 3 | use std::fs; 4 | use std::path::Path; 5 | use std::path::PathBuf; 6 | 7 | fn main() { 8 | // from aow-rust 9 | let root_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); 10 | 11 | let dest_dir = get_out_path(&root_dir, "assets/"); 12 | let asset_source_path = Path::new(&root_dir).join("assets"); 13 | 14 | println!("Copying assets from: {}", asset_source_path.display()); 15 | 16 | let paths = fs::read_dir(asset_source_path).unwrap(); 17 | 18 | if !dest_dir.exists() { 19 | fs::create_dir(dest_dir).expect("unable to create dir"); 20 | } 21 | 22 | for entry in paths { 23 | let path = entry.unwrap().path(); 24 | if path.is_dir() { 25 | // TODO: implement recursive copy 26 | } else { 27 | let assets = "assets/".to_owned(); 28 | let file_name = assets + path.file_name().unwrap().to_str().unwrap(); 29 | println!("Filename: {}", file_name); 30 | let dest = get_out_path(&root_dir, &file_name); 31 | println!("Destination Path: {}", dest.display()); 32 | match fs::copy(&path, dest) { 33 | Ok(s) => println!("Copied: {}", s), 34 | Err(err) => println!("Error: {}", err), 35 | } 36 | } 37 | } 38 | } 39 | 40 | fn get_out_path(out_dir: &str, file_name: &str) -> PathBuf { 41 | let debug = match env::var("DEBUG") { 42 | Ok(s) => s == "true", 43 | _ => false, 44 | }; 45 | if debug { 46 | return Path::new(&out_dir).join("target/debug/").join(file_name); 47 | } 48 | 49 | Path::new(&out_dir).join("target/release/").join(file_name) 50 | } 51 | -------------------------------------------------------------------------------- /clean: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shortcut to recompile both game_state and mod_rendering, in case of working on rendering innards 3 | export RUST_BACKTRACE=full 4 | set -e 5 | #boop 6 | (cd game_state && cargo clean $1) 7 | (cd mod_rendering_opengl && cargo clean $1) 8 | (cd mod_rendering_vulkano && cargo clean $1) 9 | #(cd mod_rendering_voodoo && cargo clean $1) 10 | (cd mod_input && cargo clean $1) 11 | (cd mod_gamepad && cargo clean $1) 12 | (cd mod_asset_loader && cargo clean $1) 13 | (cd mod_simulation && cargo clean $1) 14 | cargo clean $1 15 | 16 | -------------------------------------------------------------------------------- /game_state/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "adler" 5 | version = "1.0.2" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 8 | 9 | [[package]] 10 | name = "adler32" 11 | version = "1.2.0" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 14 | 15 | [[package]] 16 | name = "approx" 17 | version = "0.4.0" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" 20 | dependencies = [ 21 | "num-traits", 22 | ] 23 | 24 | [[package]] 25 | name = "arrayvec" 26 | version = "0.4.11" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" 29 | dependencies = [ 30 | "nodrop", 31 | ] 32 | 33 | [[package]] 34 | name = "autocfg" 35 | version = "0.1.6" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" 38 | 39 | [[package]] 40 | name = "autocfg" 41 | version = "1.0.0" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 44 | 45 | [[package]] 46 | name = "base-x" 47 | version = "0.2.6" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" 50 | 51 | [[package]] 52 | name = "bitflags" 53 | version = "1.2.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 56 | 57 | [[package]] 58 | name = "bumpalo" 59 | version = "3.1.2" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" 62 | 63 | [[package]] 64 | name = "bytemuck" 65 | version = "1.5.1" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" 68 | 69 | [[package]] 70 | name = "byteorder" 71 | version = "1.3.2" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 74 | 75 | [[package]] 76 | name = "cfg-if" 77 | version = "0.1.10" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 80 | 81 | [[package]] 82 | name = "cfg-if" 83 | version = "1.0.0" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 86 | 87 | [[package]] 88 | name = "color_quant" 89 | version = "1.1.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 92 | 93 | [[package]] 94 | name = "crc32fast" 95 | version = "1.2.1" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 98 | dependencies = [ 99 | "cfg-if 1.0.0", 100 | ] 101 | 102 | [[package]] 103 | name = "crossbeam-deque" 104 | version = "0.6.3" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" 107 | dependencies = [ 108 | "crossbeam-epoch", 109 | "crossbeam-utils", 110 | ] 111 | 112 | [[package]] 113 | name = "crossbeam-epoch" 114 | version = "0.7.2" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 117 | dependencies = [ 118 | "arrayvec", 119 | "cfg-if 0.1.10", 120 | "crossbeam-utils", 121 | "lazy_static", 122 | "memoffset", 123 | "scopeguard", 124 | ] 125 | 126 | [[package]] 127 | name = "crossbeam-queue" 128 | version = "0.1.2" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 131 | dependencies = [ 132 | "crossbeam-utils", 133 | ] 134 | 135 | [[package]] 136 | name = "crossbeam-utils" 137 | version = "0.6.6" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 140 | dependencies = [ 141 | "cfg-if 0.1.10", 142 | "lazy_static", 143 | ] 144 | 145 | [[package]] 146 | name = "deflate" 147 | version = "0.8.6" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" 150 | dependencies = [ 151 | "adler32", 152 | "byteorder", 153 | ] 154 | 155 | [[package]] 156 | name = "discard" 157 | version = "1.0.4" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 160 | 161 | [[package]] 162 | name = "downcast-rs" 163 | version = "1.1.1" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" 166 | 167 | [[package]] 168 | name = "either" 169 | version = "1.5.2" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" 172 | 173 | [[package]] 174 | name = "fixedbitset" 175 | version = "0.2.0" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" 178 | 179 | [[package]] 180 | name = "futures" 181 | version = "0.3.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" 184 | dependencies = [ 185 | "futures-channel", 186 | "futures-core", 187 | "futures-executor", 188 | "futures-io", 189 | "futures-sink", 190 | "futures-task", 191 | "futures-util", 192 | ] 193 | 194 | [[package]] 195 | name = "futures-channel" 196 | version = "0.3.1" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" 199 | dependencies = [ 200 | "futures-core", 201 | "futures-sink", 202 | ] 203 | 204 | [[package]] 205 | name = "futures-core" 206 | version = "0.3.1" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" 209 | 210 | [[package]] 211 | name = "futures-executor" 212 | version = "0.3.1" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" 215 | dependencies = [ 216 | "futures-core", 217 | "futures-task", 218 | "futures-util", 219 | ] 220 | 221 | [[package]] 222 | name = "futures-io" 223 | version = "0.3.1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" 226 | 227 | [[package]] 228 | name = "futures-macro" 229 | version = "0.3.1" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" 232 | dependencies = [ 233 | "proc-macro-hack", 234 | "proc-macro2", 235 | "quote", 236 | "syn", 237 | ] 238 | 239 | [[package]] 240 | name = "futures-sink" 241 | version = "0.3.1" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" 244 | 245 | [[package]] 246 | name = "futures-task" 247 | version = "0.3.1" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" 250 | 251 | [[package]] 252 | name = "futures-util" 253 | version = "0.3.1" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" 256 | dependencies = [ 257 | "futures-channel", 258 | "futures-core", 259 | "futures-io", 260 | "futures-macro", 261 | "futures-sink", 262 | "futures-task", 263 | "memchr", 264 | "pin-utils", 265 | "proc-macro-hack", 266 | "proc-macro-nested", 267 | "slab", 268 | ] 269 | 270 | [[package]] 271 | name = "game_state" 272 | version = "0.2.0" 273 | dependencies = [ 274 | "futures", 275 | "image", 276 | "nalgebra", 277 | "nom-obj", 278 | "nphysics3d", 279 | "sdl2", 280 | "serde", 281 | ] 282 | 283 | [[package]] 284 | name = "generational-arena" 285 | version = "0.2.7" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "0e40d0cee2e2fb4fba18b55a27bf96faf49fa86d49f178695bd3bf4500b156b4" 288 | dependencies = [ 289 | "cfg-if 0.1.10", 290 | ] 291 | 292 | [[package]] 293 | name = "gif" 294 | version = "0.11.2" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" 297 | dependencies = [ 298 | "color_quant", 299 | "weezl", 300 | ] 301 | 302 | [[package]] 303 | name = "hashbrown" 304 | version = "0.9.1" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 307 | 308 | [[package]] 309 | name = "image" 310 | version = "0.23.14" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" 313 | dependencies = [ 314 | "bytemuck", 315 | "byteorder", 316 | "color_quant", 317 | "gif", 318 | "jpeg-decoder", 319 | "num-iter", 320 | "num-rational", 321 | "num-traits", 322 | "png", 323 | "scoped_threadpool", 324 | "tiff", 325 | ] 326 | 327 | [[package]] 328 | name = "indexmap" 329 | version = "1.6.2" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" 332 | dependencies = [ 333 | "autocfg 1.0.0", 334 | "hashbrown", 335 | ] 336 | 337 | [[package]] 338 | name = "instant" 339 | version = "0.1.2" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf" 342 | dependencies = [ 343 | "stdweb", 344 | "time", 345 | ] 346 | 347 | [[package]] 348 | name = "itoa" 349 | version = "0.4.5" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 352 | 353 | [[package]] 354 | name = "jpeg-decoder" 355 | version = "0.1.22" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" 358 | dependencies = [ 359 | "rayon", 360 | ] 361 | 362 | [[package]] 363 | name = "lazy_static" 364 | version = "1.4.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 367 | 368 | [[package]] 369 | name = "libc" 370 | version = "0.2.94" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" 373 | 374 | [[package]] 375 | name = "log" 376 | version = "0.4.8" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 379 | dependencies = [ 380 | "cfg-if 0.1.10", 381 | ] 382 | 383 | [[package]] 384 | name = "matrixmultiply" 385 | version = "0.3.1" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "5a8a15b776d9dfaecd44b03c5828c2199cddff5247215858aac14624f8d6b741" 388 | dependencies = [ 389 | "rawpointer", 390 | ] 391 | 392 | [[package]] 393 | name = "memchr" 394 | version = "2.2.1" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 397 | 398 | [[package]] 399 | name = "memoffset" 400 | version = "0.5.1" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" 403 | dependencies = [ 404 | "rustc_version", 405 | ] 406 | 407 | [[package]] 408 | name = "miniz_oxide" 409 | version = "0.3.7" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 412 | dependencies = [ 413 | "adler32", 414 | ] 415 | 416 | [[package]] 417 | name = "miniz_oxide" 418 | version = "0.4.4" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 421 | dependencies = [ 422 | "adler", 423 | "autocfg 1.0.0", 424 | ] 425 | 426 | [[package]] 427 | name = "nalgebra" 428 | version = "0.26.2" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "476d1d59fe02fe54c86356e91650cd892f392782a1cb9fc524ec84f7aa9e1d06" 431 | dependencies = [ 432 | "approx", 433 | "matrixmultiply", 434 | "num-complex", 435 | "num-rational", 436 | "num-traits", 437 | "simba", 438 | "typenum", 439 | ] 440 | 441 | [[package]] 442 | name = "ncollide3d" 443 | version = "0.29.0" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "57e1b8b0e8696557b00224e92289ad279c7c12679a904bdc640be5c3eabdaa36" 446 | dependencies = [ 447 | "approx", 448 | "bitflags", 449 | "downcast-rs", 450 | "either", 451 | "nalgebra", 452 | "num-traits", 453 | "petgraph", 454 | "simba", 455 | "slab", 456 | "slotmap", 457 | "smallvec", 458 | ] 459 | 460 | [[package]] 461 | name = "nodrop" 462 | version = "0.1.13" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | checksum = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 465 | 466 | [[package]] 467 | name = "nom" 468 | version = "2.2.1" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff" 471 | 472 | [[package]] 473 | name = "nom-obj" 474 | version = "0.2.0" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "c0a203a8b25ac1d7a07ba403bce1119f90918c7d928db59ed65181bdf2a2841b" 477 | dependencies = [ 478 | "nom", 479 | ] 480 | 481 | [[package]] 482 | name = "nphysics3d" 483 | version = "0.21.0" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "6994fb4f4c5e2d1fc4d9507213982a80f71587d77900e9ba0e07fc50762322be" 486 | dependencies = [ 487 | "approx", 488 | "bitflags", 489 | "downcast-rs", 490 | "either", 491 | "generational-arena", 492 | "instant", 493 | "lazy_static", 494 | "nalgebra", 495 | "ncollide3d", 496 | "num-traits", 497 | "simba", 498 | "slotmap", 499 | "smallvec", 500 | "stdweb", 501 | ] 502 | 503 | [[package]] 504 | name = "num-complex" 505 | version = "0.3.1" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 508 | dependencies = [ 509 | "num-traits", 510 | ] 511 | 512 | [[package]] 513 | name = "num-integer" 514 | version = "0.1.42" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" 517 | dependencies = [ 518 | "autocfg 1.0.0", 519 | "num-traits", 520 | ] 521 | 522 | [[package]] 523 | name = "num-iter" 524 | version = "0.1.39" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" 527 | dependencies = [ 528 | "autocfg 0.1.6", 529 | "num-integer", 530 | "num-traits", 531 | ] 532 | 533 | [[package]] 534 | name = "num-rational" 535 | version = "0.3.2" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 538 | dependencies = [ 539 | "autocfg 1.0.0", 540 | "num-integer", 541 | "num-traits", 542 | ] 543 | 544 | [[package]] 545 | name = "num-traits" 546 | version = "0.2.11" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" 549 | dependencies = [ 550 | "autocfg 1.0.0", 551 | ] 552 | 553 | [[package]] 554 | name = "num_cpus" 555 | version = "1.10.1" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" 558 | dependencies = [ 559 | "libc", 560 | ] 561 | 562 | [[package]] 563 | name = "paste" 564 | version = "1.0.5" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" 567 | 568 | [[package]] 569 | name = "petgraph" 570 | version = "0.5.1" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" 573 | dependencies = [ 574 | "fixedbitset", 575 | "indexmap", 576 | ] 577 | 578 | [[package]] 579 | name = "pin-utils" 580 | version = "0.1.0-alpha.4" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" 583 | 584 | [[package]] 585 | name = "png" 586 | version = "0.16.8" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" 589 | dependencies = [ 590 | "bitflags", 591 | "crc32fast", 592 | "deflate", 593 | "miniz_oxide 0.3.7", 594 | ] 595 | 596 | [[package]] 597 | name = "proc-macro-hack" 598 | version = "0.5.11" 599 | source = "registry+https://github.com/rust-lang/crates.io-index" 600 | checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" 601 | dependencies = [ 602 | "proc-macro2", 603 | "quote", 604 | "syn", 605 | ] 606 | 607 | [[package]] 608 | name = "proc-macro-nested" 609 | version = "0.1.3" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" 612 | 613 | [[package]] 614 | name = "proc-macro2" 615 | version = "1.0.7" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" 618 | dependencies = [ 619 | "unicode-xid", 620 | ] 621 | 622 | [[package]] 623 | name = "quote" 624 | version = "1.0.2" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 627 | dependencies = [ 628 | "proc-macro2", 629 | ] 630 | 631 | [[package]] 632 | name = "rawpointer" 633 | version = "0.2.1" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" 636 | 637 | [[package]] 638 | name = "rayon" 639 | version = "1.1.0" 640 | source = "registry+https://github.com/rust-lang/crates.io-index" 641 | checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" 642 | dependencies = [ 643 | "crossbeam-deque", 644 | "either", 645 | "rayon-core", 646 | ] 647 | 648 | [[package]] 649 | name = "rayon-core" 650 | version = "1.5.0" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" 653 | dependencies = [ 654 | "crossbeam-deque", 655 | "crossbeam-queue", 656 | "crossbeam-utils", 657 | "lazy_static", 658 | "num_cpus", 659 | ] 660 | 661 | [[package]] 662 | name = "redox_syscall" 663 | version = "0.1.56" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 666 | 667 | [[package]] 668 | name = "rustc_version" 669 | version = "0.2.3" 670 | source = "registry+https://github.com/rust-lang/crates.io-index" 671 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 672 | dependencies = [ 673 | "semver", 674 | ] 675 | 676 | [[package]] 677 | name = "ryu" 678 | version = "1.0.2" 679 | source = "registry+https://github.com/rust-lang/crates.io-index" 680 | checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 681 | 682 | [[package]] 683 | name = "scoped_threadpool" 684 | version = "0.1.9" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 687 | 688 | [[package]] 689 | name = "scopeguard" 690 | version = "1.0.0" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 693 | 694 | [[package]] 695 | name = "sdl2" 696 | version = "0.34.5" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "deecbc3fa9460acff5a1e563e05cb5f31bba0aa0c214bb49a43db8159176d54b" 699 | dependencies = [ 700 | "bitflags", 701 | "lazy_static", 702 | "libc", 703 | "sdl2-sys", 704 | ] 705 | 706 | [[package]] 707 | name = "sdl2-sys" 708 | version = "0.34.5" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "41a29aa21f175b5a41a6e26da572d5e5d1ee5660d35f9f9d0913e8a802098f74" 711 | dependencies = [ 712 | "cfg-if 0.1.10", 713 | "libc", 714 | "version-compare", 715 | ] 716 | 717 | [[package]] 718 | name = "semver" 719 | version = "0.9.0" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 722 | dependencies = [ 723 | "semver-parser", 724 | ] 725 | 726 | [[package]] 727 | name = "semver-parser" 728 | version = "0.7.0" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 731 | 732 | [[package]] 733 | name = "serde" 734 | version = "1.0.99" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" 737 | 738 | [[package]] 739 | name = "serde_derive" 740 | version = "1.0.104" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" 743 | dependencies = [ 744 | "proc-macro2", 745 | "quote", 746 | "syn", 747 | ] 748 | 749 | [[package]] 750 | name = "serde_json" 751 | version = "1.0.45" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "eab8f15f15d6c41a154c1b128a22f2dfabe350ef53c40953d84e36155c91192b" 754 | dependencies = [ 755 | "itoa", 756 | "ryu", 757 | "serde", 758 | ] 759 | 760 | [[package]] 761 | name = "sha1" 762 | version = "0.6.0" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 765 | 766 | [[package]] 767 | name = "simba" 768 | version = "0.4.0" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "5132a955559188f3d13c9ba831e77c802ddc8782783f050ed0c52f5988b95f4c" 771 | dependencies = [ 772 | "approx", 773 | "num-complex", 774 | "num-traits", 775 | "paste", 776 | ] 777 | 778 | [[package]] 779 | name = "slab" 780 | version = "0.4.2" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 783 | 784 | [[package]] 785 | name = "slotmap" 786 | version = "1.0.3" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "585cd5dffe4e9e06f6dfdf66708b70aca3f781bed561f4f667b2d9c0d4559e36" 789 | dependencies = [ 790 | "version_check", 791 | ] 792 | 793 | [[package]] 794 | name = "smallvec" 795 | version = "1.6.1" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 798 | 799 | [[package]] 800 | name = "stdweb" 801 | version = "0.4.20" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 804 | dependencies = [ 805 | "discard", 806 | "rustc_version", 807 | "serde", 808 | "serde_json", 809 | "stdweb-derive", 810 | "stdweb-internal-macros", 811 | "stdweb-internal-runtime", 812 | "wasm-bindgen", 813 | ] 814 | 815 | [[package]] 816 | name = "stdweb-derive" 817 | version = "0.5.3" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 820 | dependencies = [ 821 | "proc-macro2", 822 | "quote", 823 | "serde", 824 | "serde_derive", 825 | "syn", 826 | ] 827 | 828 | [[package]] 829 | name = "stdweb-internal-macros" 830 | version = "0.2.9" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 833 | dependencies = [ 834 | "base-x", 835 | "proc-macro2", 836 | "quote", 837 | "serde", 838 | "serde_derive", 839 | "serde_json", 840 | "sha1", 841 | "syn", 842 | ] 843 | 844 | [[package]] 845 | name = "stdweb-internal-runtime" 846 | version = "0.1.5" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 849 | 850 | [[package]] 851 | name = "syn" 852 | version = "1.0.13" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" 855 | dependencies = [ 856 | "proc-macro2", 857 | "quote", 858 | "unicode-xid", 859 | ] 860 | 861 | [[package]] 862 | name = "tiff" 863 | version = "0.6.1" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" 866 | dependencies = [ 867 | "jpeg-decoder", 868 | "miniz_oxide 0.4.4", 869 | "weezl", 870 | ] 871 | 872 | [[package]] 873 | name = "time" 874 | version = "0.1.42" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 877 | dependencies = [ 878 | "libc", 879 | "redox_syscall", 880 | "winapi", 881 | ] 882 | 883 | [[package]] 884 | name = "typenum" 885 | version = "1.13.0" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 888 | 889 | [[package]] 890 | name = "unicode-xid" 891 | version = "0.2.0" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 894 | 895 | [[package]] 896 | name = "version-compare" 897 | version = "0.0.10" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" 900 | 901 | [[package]] 902 | name = "version_check" 903 | version = "0.9.3" 904 | source = "registry+https://github.com/rust-lang/crates.io-index" 905 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 906 | 907 | [[package]] 908 | name = "wasm-bindgen" 909 | version = "0.2.58" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" 912 | dependencies = [ 913 | "cfg-if 0.1.10", 914 | "wasm-bindgen-macro", 915 | ] 916 | 917 | [[package]] 918 | name = "wasm-bindgen-backend" 919 | version = "0.2.58" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" 922 | dependencies = [ 923 | "bumpalo", 924 | "lazy_static", 925 | "log", 926 | "proc-macro2", 927 | "quote", 928 | "syn", 929 | "wasm-bindgen-shared", 930 | ] 931 | 932 | [[package]] 933 | name = "wasm-bindgen-macro" 934 | version = "0.2.58" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" 937 | dependencies = [ 938 | "quote", 939 | "wasm-bindgen-macro-support", 940 | ] 941 | 942 | [[package]] 943 | name = "wasm-bindgen-macro-support" 944 | version = "0.2.58" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" 947 | dependencies = [ 948 | "proc-macro2", 949 | "quote", 950 | "syn", 951 | "wasm-bindgen-backend", 952 | "wasm-bindgen-shared", 953 | ] 954 | 955 | [[package]] 956 | name = "wasm-bindgen-shared" 957 | version = "0.2.58" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" 960 | 961 | [[package]] 962 | name = "weezl" 963 | version = "0.1.5" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" 966 | 967 | [[package]] 968 | name = "winapi" 969 | version = "0.3.7" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 972 | dependencies = [ 973 | "winapi-i686-pc-windows-gnu", 974 | "winapi-x86_64-pc-windows-gnu", 975 | ] 976 | 977 | [[package]] 978 | name = "winapi-i686-pc-windows-gnu" 979 | version = "0.4.0" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 982 | 983 | [[package]] 984 | name = "winapi-x86_64-pc-windows-gnu" 985 | version = "0.4.0" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 988 | -------------------------------------------------------------------------------- /game_state/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "game_state" 3 | version = "0.2.0" 4 | authors = ["Daniel Werner "] 5 | edition = "2018" 6 | 7 | [features] 8 | default = [] 9 | dynamic_lib = [] 10 | 11 | [lib] 12 | name = "game_state" 13 | crate-type=["rlib"] 14 | 15 | [dependencies] 16 | 17 | # needs to match all other modules 18 | sdl2 = "0.34" 19 | nalgebra = "0.26" 20 | image = "0.23" 21 | nom-obj = "0.2" 22 | serde = "1" 23 | futures="0.3.1" 24 | nphysics3d = "0.21" 25 | -------------------------------------------------------------------------------- /game_state/README.md: -------------------------------------------------------------------------------- 1 | # `game_state` 2 | 3 | This crate is responsible for defining `State` and related access traits, as well as common 'interface-structs' that 4 | are used throughout the system. If at all possible, keep mod-specific functionality in the modules themselves. 5 | -------------------------------------------------------------------------------- /game_state/benches/node.rs: -------------------------------------------------------------------------------- 1 | extern crate game_state; 2 | 3 | #[cfg(test)] 4 | mod tests {} 5 | -------------------------------------------------------------------------------- /game_state/build.rs: -------------------------------------------------------------------------------- 1 | 2 | fn main() { 3 | println!("Don't forget about me! (build.rs)"); 4 | 5 | } 6 | -------------------------------------------------------------------------------- /game_state/examples/nodes.rs: -------------------------------------------------------------------------------- 1 | extern crate game_state; 2 | 3 | use game_state::tree::Node; 4 | 5 | fn main() { 6 | let root_rc = Node::create(0, None); 7 | // Child consumes ownership of parent as *mut, now lost by lifetimes 8 | for x in 1..10 { 9 | let child = Node::create(0, Some(root_rc.clone())); 10 | for _y in 1..x { 11 | let _subchild = Node::create(0, Some(child.clone())); 12 | } 13 | } 14 | 15 | let pb = root_rc.borrow(); 16 | pb.debug_draw(0); 17 | } 18 | -------------------------------------------------------------------------------- /game_state/src/event.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex, Weak}; 2 | 3 | use std::collections::HashMap; 4 | 5 | /// Since we want cross-thread handling of input, we choose Arc 6 | pub type EventHandler = dyn Fn(T) -> (); 7 | pub type ArcEventHandler = Arc>>>; 8 | pub type WeakEventHandler = Weak>>>; 9 | 10 | pub trait EventProducer 11 | where 12 | T: Clone, 13 | { 14 | fn add_handler(&mut self, id: String, handler: &ArcEventHandler); 15 | fn remove_handler(&mut self, id: &str); 16 | fn publish(&mut self, event: T); 17 | } 18 | 19 | pub struct CopyingEventProducer { 20 | handlers: HashMap>, 21 | } 22 | 23 | impl CopyingEventProducer { 24 | pub fn new() -> Self { 25 | CopyingEventProducer { 26 | handlers: HashMap::new(), 27 | } 28 | } 29 | pub fn create_handler ()>(func: F) -> ArcEventHandler 30 | where 31 | F: 'static, 32 | { 33 | Arc::new(Mutex::new(Box::new(func))) 34 | } 35 | } 36 | 37 | impl EventProducer for CopyingEventProducer 38 | where 39 | T: Clone, 40 | { 41 | fn add_handler(&mut self, id: String, handler: &ArcEventHandler) { 42 | let wh: WeakEventHandler = Arc::downgrade(handler); 43 | self.handlers.entry(id).or_insert(wh); 44 | } 45 | 46 | fn remove_handler(&mut self, id: &str) { 47 | self.handlers.remove(id); 48 | } 49 | 50 | fn publish(&mut self, event: T) { 51 | for (_id, handler) in self.handlers.iter() { 52 | match handler.upgrade() { 53 | Some(a) => { 54 | (*a.lock().unwrap())(event.clone()); 55 | } 56 | None => {} //arc has been dropped, TODO: notify or log? 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /game_state/src/input/events.rs: -------------------------------------------------------------------------------- 1 | use crate::input::screen::{DeltaVector, ScreenPoint}; 2 | use crate::Identity; 3 | 4 | #[derive(Debug, Clone)] 5 | pub enum MouseButton { 6 | Left, 7 | Middle, 8 | Right, 9 | Other(u8), 10 | } 11 | 12 | pub type DeviceId = usize; 13 | 14 | #[derive(Debug, Clone)] 15 | pub enum JoyAxis { 16 | LeftStickX, 17 | LeftStickY, 18 | LeftZ, 19 | RightStickX, 20 | RightStickY, 21 | RightZ, 22 | DPadX, 23 | DPadY, 24 | Unknown, 25 | } 26 | 27 | #[derive(Debug, Clone)] 28 | pub enum JoyButton { 29 | South, 30 | East, 31 | North, 32 | West, 33 | C, 34 | Z, 35 | LeftTrigger, 36 | LeftTrigger2, 37 | RightTrigger, 38 | RightTrigger2, 39 | Select, 40 | Start, 41 | Mode, 42 | LeftThumb, 43 | RightThumb, 44 | DPadUp, 45 | DPadDown, 46 | DPadLeft, 47 | DPadRight, 48 | Unknown, 49 | } 50 | 51 | #[derive(Debug, Clone)] 52 | pub enum InputEvent { 53 | KeyDown(Identity, u32), 54 | KeyUp(Identity, u32), 55 | 56 | MouseDown(Identity, MouseButton), 57 | MouseUp(Identity, MouseButton), 58 | MouseMove(Identity, ScreenPoint), 59 | MouseWheel(Identity, DeltaVector), 60 | 61 | MouseEntered(Identity), 62 | MouseLeft(Identity), 63 | 64 | JoyAxisChanged(Identity, DeviceId, JoyAxis, f32), 65 | JoyButtonDown(Identity, DeviceId, JoyButton), 66 | JoyButtonRepeated(Identity, DeviceId, JoyButton), 67 | JoyButtonChanged(Identity, DeviceId, JoyButton, f32), 68 | JoyButtonUp(Identity, DeviceId, JoyButton), 69 | JoyConnected(Identity, DeviceId), 70 | JoyDisconnected(Identity, DeviceId), 71 | JoyEventDropped(Identity, DeviceId), 72 | 73 | CloseRequested(Identity), 74 | Destroyed(Identity), 75 | Resized(Identity, f32, f32), 76 | GainedFocus(Identity), 77 | LostFocus(Identity), 78 | Moved(Identity, ScreenPoint), 79 | } 80 | 81 | #[cfg(test)] 82 | mod tests { 83 | use super::*; 84 | 85 | use crate::event::{CopyingEventProducer, EventProducer}; 86 | 87 | use std::sync::{Arc, Mutex}; 88 | 89 | pub type KeysDown = [bool; 256]; 90 | 91 | struct KeydownState { 92 | keys_down: KeysDown, 93 | } 94 | impl KeydownState { 95 | fn get_keys(&self) -> &KeysDown { 96 | &self.keys_down 97 | } 98 | // fn set_keys(&mut self, keys: KeysDown) { self.keys_down = keys; } 99 | } 100 | 101 | #[test] 102 | fn input_publisher_publishes_events() { 103 | let id = 0u64 as Identity; 104 | let s1 = KeydownState { 105 | keys_down: [false; 256], 106 | }; 107 | let state = Arc::new(Mutex::new(s1)); 108 | let closed_state = state.clone(); 109 | 110 | let handler1 = CopyingEventProducer::::create_handler( 111 | move |event: InputEvent| match event { 112 | InputEvent::KeyDown(_id, code) => { 113 | closed_state.lock().unwrap().keys_down[code as usize] = true; 114 | } 115 | InputEvent::KeyUp(_id, code) => { 116 | closed_state.lock().unwrap().keys_down[code as usize] = false; 117 | } 118 | _ => { 119 | panic!("Nope!"); 120 | } 121 | }, 122 | ); 123 | 124 | let down_event = InputEvent::KeyDown(id, 42); 125 | let up_event = InputEvent::KeyUp(id, 42); 126 | 127 | let mut producer = CopyingEventProducer::::new(); 128 | 129 | let handler_id = "input_handler_id".to_string(); 130 | producer.add_handler(handler_id.clone(), &handler1); 131 | 132 | // Initial state is unpressed 133 | let not_pressed = !state.lock().unwrap().get_keys()[42]; 134 | assert!(not_pressed); 135 | 136 | producer.publish(down_event.clone()); 137 | let pressed = state.lock().unwrap().get_keys()[42]; 138 | assert!(pressed); 139 | 140 | producer.publish(up_event); 141 | let not_pressed = !state.lock().unwrap().get_keys()[42]; 142 | assert!(not_pressed); 143 | 144 | producer.remove_handler(&handler_id); 145 | producer.publish(down_event); 146 | let pressed = state.lock().unwrap().get_keys()[42]; 147 | assert!(!pressed); 148 | 149 | let evt = InputEvent::KeyDown(id, 69); 150 | producer.publish(evt); 151 | } 152 | 153 | #[test] 154 | fn input_handler_handles_events() { 155 | // TODO:.... 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /game_state/src/input/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod events; 2 | pub mod screen; 3 | -------------------------------------------------------------------------------- /game_state/src/input/screen.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone)] 2 | pub struct ScreenPoint { 3 | pub x: i32, 4 | pub y: i32, 5 | } 6 | 7 | impl ScreenPoint { 8 | pub fn new(x: i32, y: i32) -> Self { 9 | ScreenPoint { x, y } 10 | } 11 | } 12 | 13 | #[derive(Debug, Clone)] 14 | pub struct ScreenRect { 15 | pub x: i32, 16 | pub y: i32, 17 | pub w: i32, 18 | pub h: i32, 19 | } 20 | 21 | impl ScreenRect { 22 | pub fn new(x: i32, y: i32, w: i32, h: i32) -> Self { 23 | ScreenRect { x, y, w, h } 24 | } 25 | pub fn intersects(&self, point: &ScreenPoint) -> bool { 26 | point.x >= self.x 27 | && point.y >= self.y 28 | && point.x < self.x + self.w 29 | && point.y < self.y + self.h 30 | } 31 | } 32 | 33 | #[derive(Debug, Clone)] 34 | pub struct DeltaVector { 35 | pub delta_x: i32, 36 | pub delta_y: i32, 37 | } 38 | 39 | impl DeltaVector { 40 | pub fn new(dx: i32, dy: i32) -> Self { 41 | DeltaVector { 42 | delta_x: dx, 43 | delta_y: dy, 44 | } 45 | } 46 | pub fn from_points(old: &ScreenPoint, new: &ScreenPoint) -> Self { 47 | Self::new(new.x - old.x, new.y - old.y) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /game_state/src/lib.rs: -------------------------------------------------------------------------------- 1 | // opinion here? reexport winit or import in other libs...? 2 | pub use nalgebra; 3 | pub use sdl2; 4 | pub use sdl2::sys as sdl2_sys; 5 | 6 | pub mod model; 7 | pub mod state; 8 | pub mod tree; 9 | 10 | pub mod event; 11 | pub mod input; 12 | pub mod thing; 13 | pub mod ui; 14 | pub mod utils; 15 | 16 | use std::sync::Arc; 17 | use std::time::Duration; 18 | 19 | use state::SceneGraph; 20 | use std::sync::atomic::{AtomicUsize, Ordering}; 21 | use thing::CameraFacet; 22 | 23 | static GLOBAL_IDENITY_CURSOR: AtomicUsize = AtomicUsize::new(0); 24 | 25 | pub type Identity = u64; 26 | pub fn create_next_identity() -> Identity { 27 | GLOBAL_IDENITY_CURSOR.fetch_add(1, Ordering::SeqCst) as Identity 28 | } 29 | 30 | pub trait Identifyable { 31 | fn identify(&self) -> Identity; 32 | } 33 | 34 | pub trait Renderer: Identifyable { 35 | /// load() 36 | /// provide a hook for a mod to notify the renderer that it is about to be used 37 | fn load(&mut self); 38 | 39 | /// unload() 40 | /// This is called by a mod to notify the renderer to be done with any state. 41 | fn unload(&mut self); 42 | 43 | /// queue_render_layer() 44 | /// Set the renderer up with a queue of SceneGraphs 45 | fn queue_render_layer(&mut self, layer: Arc); 46 | 47 | /// present() 48 | /// Actually render the image, compositing render layers in the order they were queued 49 | fn present(&mut self, camera: &CameraFacet); 50 | } 51 | 52 | pub trait Behavior { 53 | fn update(delta_time: &Duration); 54 | } 55 | -------------------------------------------------------------------------------- /game_state/src/model.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::path::Path; 3 | 4 | use nalgebra::Matrix4; 5 | 6 | // TODO: still need to refactor nom-obj to take BufReader, among other things 7 | use nom_obj::model::{Interleaved, Obj}; 8 | 9 | use crate::create_next_identity; 10 | use crate::Identifyable; 11 | use crate::Identity; 12 | 13 | #[derive(Clone)] 14 | pub struct Material { 15 | pub diffuse_map: image::DynamicImage, 16 | } 17 | 18 | #[derive(Clone)] 19 | pub struct Model { 20 | pub filename: String, 21 | pub id: Identity, 22 | pub model_mat: Matrix4, 23 | pub world_mat: Matrix4, 24 | pub material: Material, 25 | pub mesh: Mesh, 26 | } 27 | 28 | impl Model { 29 | pub fn load(filename: &str, model_mat: Matrix4) -> Result, Box> { 30 | let obj = Obj::read_file(filename)?; 31 | 32 | let mut models = Vec::new(); 33 | for o in obj.objects.iter() { 34 | let Interleaved { v_vt_vn, idx } = o.interleaved(); 35 | 36 | let verts = v_vt_vn 37 | .iter() 38 | .map(|&(v, vt, vn)| Vertex::new((v.0, v.1, v.2), vt, (vn.0, vn.1, vn.2))) 39 | .collect::>(); 40 | 41 | if verts.is_empty() { 42 | return Err("model has no vertices".into()); 43 | } 44 | 45 | let indices = idx.iter().map(|x: &usize| *x as u16).collect::>(); 46 | 47 | let diffuse_map_filename = &obj.objects[0] 48 | .material 49 | .as_ref() 50 | .ok_or_else(|| format!("no diffuse map (map_Kd) defined in model {}", filename))? 51 | .diffuse_map; 52 | 53 | let material_path = Path::new(diffuse_map_filename); 54 | let diffuse_map = image::open(material_path)?; 55 | 56 | models.push(Model { 57 | filename: filename.to_string(), 58 | id: create_next_identity(), 59 | model_mat, 60 | world_mat: Matrix4::::identity(), 61 | mesh: Mesh::create(verts, indices), 62 | material: Material { diffuse_map }, 63 | }) 64 | } 65 | 66 | Ok(models) 67 | } 68 | } 69 | 70 | #[test] 71 | #[cfg(test)] 72 | fn slice_windows_learning() { 73 | let vec1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 74 | let vec2 = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; 75 | let vec3 = [10, 11, 12, 13, 14, 15, 16]; 76 | 77 | let one = vec1.windows(3); 78 | let two = vec2.windows(3); 79 | let three = vec3.windows(2); 80 | 81 | for ((a, b), c) in one.zip(two).zip(three) { 82 | assert_eq!(a.len(), 3); 83 | assert_eq!(b.len(), 3); 84 | assert_eq!(c.len(), 2); 85 | } 86 | 87 | //let model = Model::create("assets/models/teapot.obj", Matrix4::::identity()); 88 | } 89 | 90 | #[derive(Debug, Copy, Clone)] 91 | pub struct Vector(pub f32, pub f32, pub f32); 92 | 93 | #[derive(Debug, Copy, Clone)] 94 | pub struct UVW(pub f32, pub f32, pub f32); 95 | 96 | #[derive(Debug, Copy, Clone)] 97 | pub struct Normal(pub f32, pub f32, pub f32); 98 | 99 | #[derive(Debug, Copy, Clone)] 100 | pub struct Vertex { 101 | pub position: Vector, 102 | pub uvw: UVW, 103 | pub normal: Normal, 104 | } 105 | 106 | impl Vertex { 107 | pub fn new(v: (f32, f32, f32), vt: (f32, f32, f32), vn: (f32, f32, f32)) -> Self { 108 | Vertex { 109 | position: Vector(v.0, v.1, v.2), 110 | uvw: UVW(vt.0, vt.1, vt.2), 111 | normal: Normal(vn.0, vn.1, vn.2), 112 | } 113 | } 114 | 115 | pub fn from_parts(v: Vector, u: UVW, n: Normal) -> Self { 116 | Vertex { 117 | position: v, 118 | uvw: u, 119 | normal: n, 120 | } 121 | } 122 | } 123 | 124 | #[derive(Clone, Debug)] 125 | pub struct Mesh { 126 | pub vertices: Vec, 127 | pub indices: Vec, 128 | } 129 | 130 | impl Mesh { 131 | pub fn create(vertices: Vec, indices: Vec) -> Self { 132 | Mesh { vertices, indices } 133 | } 134 | } 135 | 136 | impl Identifyable for Model { 137 | fn identify(&self) -> u64 { 138 | self.id 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /game_state/src/state/access.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::error::Error; 3 | use std::rc::Rc; 4 | use std::sync::Arc; 5 | 6 | use sdl2::video::WindowContext; 7 | 8 | use super::DrawMode; 9 | use super::Model; 10 | use super::Renderer; 11 | 12 | use crate::input::events::InputEvent; 13 | use crate::input::screen::ScreenPoint; 14 | use crate::state::render_state::WindowWithAttrs; 15 | use crate::state::{SceneGraph, State, World}; 16 | use crate::ui::events::UIEvent; 17 | use crate::Identity; 18 | 19 | use crate::state::Variable; 20 | 21 | pub trait WorldAccess { 22 | fn get_world(&mut self) -> &mut World; 23 | } 24 | 25 | pub trait ModelAccess { 26 | fn get_models(&self) -> Vec>; 27 | fn add_model(&mut self, model: Arc); 28 | } 29 | 30 | pub trait VariableAccess { 31 | fn get_bool(&self, key: &'static str) -> Option; 32 | fn set_bool(&mut self, key: &'static str, value: bool); 33 | fn bool_exists(&self, key: &'static str) -> bool { 34 | self.get_bool(key).is_some() 35 | } 36 | } 37 | 38 | pub trait WindowAccess { 39 | fn add_window(&mut self, w: u32, h: u32, title: &str, x: i32, y: i32, draw_mode: DrawMode); 40 | fn get_windows(&mut self) -> Vec<(Rc, DrawMode)>; 41 | } 42 | 43 | // Accessor trait for State by topic 44 | pub trait RenderAccess { 45 | fn get_renderers(&mut self) -> &Vec>; 46 | fn add_renderer(&mut self, renderer: Box); 47 | fn clear_renderers(&mut self); 48 | fn present_all(&mut self); 49 | fn remove_renderer(&mut self, id: Identity); 50 | fn push_render_layers(&mut self); 51 | 52 | fn on_render_load(&mut self); 53 | fn on_render_unload(&mut self); 54 | } 55 | 56 | pub trait RenderLayerAccess { 57 | fn get_render_layers(&mut self) -> &Vec>; 58 | fn add_render_layer(&mut self, layer: Arc); 59 | fn clear_render_layers(&mut self); 60 | } 61 | 62 | pub trait InputAccess { 63 | fn has_pending_input_events(&self) -> bool; 64 | fn clear_input_events(&mut self); 65 | fn get_input_events(&mut self) -> &VecDeque; 66 | fn send_input_event(&mut self, event: InputEvent) -> Result<(), Box>; 67 | fn on_input_load(&mut self); 68 | fn on_input_unload(&mut self); 69 | fn get_mouse_pos(&self) -> &ScreenPoint; 70 | fn set_mouse_pos(&mut self, sp: ScreenPoint); 71 | } 72 | 73 | pub trait UIAccess { 74 | fn pending_ui_events(&mut self) -> &VecDeque; 75 | fn queue_ui_event(&mut self, event: UIEvent); 76 | fn on_ui_load(&mut self); 77 | fn on_ui_unload(&mut self); 78 | } 79 | 80 | impl VariableAccess for State { 81 | fn get_bool(&self, key: &'static str) -> Option { 82 | self.variables.get(key).map(|Variable::Bool(v)| *v) 83 | } 84 | 85 | fn set_bool(&mut self, key: &'static str, value: bool) { 86 | self.variables.insert(key, Variable::Bool(value)); 87 | } 88 | } 89 | 90 | impl ModelAccess for State { 91 | fn get_models(&self) -> Vec> { 92 | self.render_state.models.clone() 93 | } 94 | 95 | fn add_model(&mut self, model: Arc) { 96 | self.render_state.models.push(model); 97 | } 98 | } 99 | 100 | impl WorldAccess for State { 101 | fn get_world(&mut self) -> &mut World { 102 | &mut self.world 103 | } 104 | } 105 | 106 | impl WindowAccess for State { 107 | // TODO: make fallible 108 | fn add_window(&mut self, w: u32, h: u32, title: &str, x: i32, y: i32, draw_mode: DrawMode) { 109 | let window = { 110 | self.sdl_subsystems 111 | .video 112 | .window(title, w, h) 113 | .position(x, y) 114 | .resizable() 115 | .allow_highdpi() 116 | .vulkan() 117 | .build() 118 | .unwrap() 119 | }; 120 | 121 | self.render_state 122 | .windows 123 | .push(WindowWithAttrs { window, draw_mode }); 124 | } 125 | 126 | fn get_windows(&mut self) -> Vec<(Rc, DrawMode)> { 127 | self.render_state 128 | .windows 129 | .iter() 130 | .map(|w| (w.window.context(), w.draw_mode)) 131 | .collect::>() 132 | } 133 | } 134 | 135 | impl RenderLayerAccess for State { 136 | fn get_render_layers(&mut self) -> &Vec> { 137 | &mut self.render_state.render_layers 138 | } 139 | 140 | fn add_render_layer(&mut self, layer: Arc) { 141 | self.render_state.render_layers.push(layer); 142 | } 143 | 144 | fn clear_render_layers(&mut self) { 145 | self.render_state.render_layers.clear(); 146 | } 147 | } 148 | 149 | impl RenderAccess for State { 150 | fn get_renderers(&mut self) -> &Vec> { 151 | &self.render_state.renderers 152 | } 153 | 154 | fn add_renderer(&mut self, renderer: Box) { 155 | self.render_state.renderers.push(renderer); 156 | } 157 | 158 | fn clear_renderers(&mut self) { 159 | self.render_state.renderers.clear(); 160 | } 161 | 162 | fn present_all(&mut self) { 163 | let camera = &self.world.get_facets().cameras[0]; 164 | for r in self.render_state.renderers.iter_mut() { 165 | r.present(camera); 166 | } 167 | } 168 | 169 | fn remove_renderer(&mut self, id: Identity) { 170 | let mut found = None; 171 | for i in 0..self.render_state.renderers.len() { 172 | if self.render_state.renderers[i].identify() == id { 173 | found = Some(i as usize); 174 | } 175 | } 176 | if let Some(found) = found { 177 | self.render_state.renderers.remove(found); 178 | } 179 | } 180 | 181 | fn push_render_layers(&mut self) { 182 | // queue each existing render layers for rendering 183 | for i in 0..self.render_state.renderers.len() { 184 | for r in &self.render_state.render_layers { 185 | self.render_state.renderers[i].queue_render_layer(r.clone()); 186 | } 187 | } 188 | } 189 | 190 | fn on_render_load(&mut self) { 191 | for i in 0..self.render_state.renderers.len() { 192 | self.render_state.renderers[i].load(); 193 | } 194 | } 195 | 196 | fn on_render_unload(&mut self) { 197 | for i in 0..self.render_state.renderers.len() { 198 | self.render_state.renderers[i].unload(); 199 | } 200 | println!("RenderAccess::on_render_unload"); 201 | self.render_state.renderers.clear(); 202 | } 203 | } 204 | 205 | impl InputAccess for State { 206 | fn has_pending_input_events(&self) -> bool { 207 | !self.input_state.get_input_events().is_empty() 208 | } 209 | 210 | fn clear_input_events(&mut self) { 211 | self.input_state.clear(); 212 | } 213 | 214 | fn get_input_events(&mut self) -> &VecDeque { 215 | &self.input_state.get_input_events() 216 | } 217 | 218 | // Input events might also come from other subsystems, so we allow them to be queued as well 219 | fn send_input_event(&mut self, event: InputEvent) -> Result<(), Box> { 220 | self.input_state.send(event) 221 | } 222 | 223 | fn on_input_load(&mut self) { 224 | self.input_state.clear(); 225 | } 226 | 227 | fn on_input_unload(&mut self) { 228 | self.input_state.clear(); 229 | } 230 | 231 | fn get_mouse_pos(&self) -> &ScreenPoint { 232 | self.input_state.get_mouse_pos() 233 | } 234 | 235 | fn set_mouse_pos(&mut self, sp: ScreenPoint) { 236 | self.input_state.set_mouse_pos(sp) 237 | } 238 | } 239 | 240 | impl UIAccess for State { 241 | fn pending_ui_events(&mut self) -> &VecDeque { 242 | &self.ui_state.pending_ui_events 243 | } 244 | 245 | fn queue_ui_event(&mut self, event: UIEvent) { 246 | self.ui_state.pending_ui_events.push_back(event); 247 | } 248 | 249 | fn on_ui_load(&mut self) { 250 | unimplemented!() 251 | } 252 | 253 | fn on_ui_unload(&mut self) { 254 | unimplemented!() 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /game_state/src/state/asset_state.rs: -------------------------------------------------------------------------------- 1 | pub struct AssetState {} 2 | 3 | impl AssetState { 4 | fn new() -> Self { 5 | AssetState {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /game_state/src/state/input_state.rs: -------------------------------------------------------------------------------- 1 | use crate::input::events::InputEvent; 2 | use crate::input::screen::ScreenPoint; 3 | use std::collections::VecDeque; 4 | use std::error::Error; 5 | 6 | pub struct InputState { 7 | events: VecDeque, 8 | mouse_pos: ScreenPoint, 9 | } 10 | 11 | impl Default for InputState { 12 | fn default() -> Self { 13 | InputState { 14 | events: Default::default(), 15 | mouse_pos: ScreenPoint::new(0, 0), 16 | } 17 | } 18 | } 19 | 20 | impl InputState { 21 | pub fn clear(&mut self) { 22 | self.events.clear(); 23 | } 24 | pub fn send(&mut self, event: InputEvent) -> Result<(), Box> { 25 | self.events.push_back(event); 26 | Ok(()) 27 | } 28 | pub fn get_input_events(&self) -> &VecDeque { 29 | &self.events 30 | } 31 | 32 | pub fn get_mouse_pos(&self) -> &ScreenPoint { 33 | &self.mouse_pos 34 | } 35 | 36 | pub fn set_mouse_pos(&mut self, sp: ScreenPoint) { 37 | self.mouse_pos = sp; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /game_state/src/state/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use super::model::Model; 4 | use super::Renderer; 5 | use crate::thing::World; 6 | 7 | pub use self::access::{ 8 | InputAccess, ModelAccess, RenderAccess, RenderLayerAccess, VariableAccess, WindowAccess, 9 | WorldAccess, 10 | }; 11 | pub use self::input_state::InputState; 12 | pub use self::render_state::{DrawMode, RenderState, SceneGraph}; 13 | pub use self::simulation_state::SimulationState; 14 | use self::ui_state::UIState; 15 | 16 | mod access; 17 | mod input_state; 18 | mod render_state; 19 | mod simulation_state; 20 | mod ui_state; 21 | 22 | /// 23 | /// This is the central, and global, state passed to each mod during the main loop 24 | /// 25 | pub struct State { 26 | pub sdl_context: sdl2::Sdl, 27 | pub sdl_subsystems: SdlSubsystems, 28 | 29 | /// Root container of the Thing/Facet system (game world state) 30 | world: World, 31 | 32 | /// Container for all rendering state 33 | render_state: RenderState, 34 | 35 | /// Container for all input state 36 | input_state: InputState, 37 | 38 | /// Container for all UI related state 39 | ui_state: UIState, 40 | 41 | // TEMPORARY container for general purpose state variables 42 | pub variables: HashMap<&'static str, Variable>, 43 | 44 | pub simulation_state: SimulationState, 45 | } 46 | 47 | #[derive(Copy, Clone)] 48 | pub enum Variable { 49 | Bool(bool), 50 | } 51 | 52 | pub struct SdlSubsystems { 53 | pub video: sdl2::VideoSubsystem, 54 | pub event_pump: sdl2::EventPump, 55 | } 56 | 57 | impl Default for State { 58 | fn default() -> Self { 59 | let ctx = sdl2::init().expect("unable to create sdl2 context"); 60 | let video = ctx.video().expect("unable to create video subsystem"); 61 | let event_pump = ctx.event_pump().expect("unable to create event pump"); 62 | Self { 63 | sdl_context: ctx, 64 | sdl_subsystems: SdlSubsystems { video, event_pump }, 65 | world: Default::default(), 66 | render_state: Default::default(), 67 | input_state: Default::default(), 68 | simulation_state: Default::default(), 69 | ui_state: Default::default(), 70 | variables: HashMap::new(), 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /game_state/src/state/render_state.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use sdl2::video::Window; 4 | 5 | use super::{Model, Renderer}; 6 | use crate::tree::RcNode; 7 | 8 | #[derive(Default)] 9 | pub struct SceneGraph>> { 10 | pub root: RcNode, 11 | } 12 | 13 | #[derive(Copy, Clone)] 14 | pub enum DrawMode { 15 | Wireframe(f32), 16 | Points, 17 | Textured, 18 | } 19 | 20 | pub struct WindowWithAttrs { 21 | pub window: Window, 22 | pub draw_mode: DrawMode, 23 | } 24 | 25 | pub struct RenderState { 26 | pub models: Vec>, 27 | pub windows: Vec, 28 | pub renderers: Vec>, 29 | pub render_layers: Vec>, 30 | } 31 | 32 | impl Default for RenderState { 33 | fn default() -> Self { 34 | Self { 35 | models: Vec::new(), 36 | windows: Vec::new(), 37 | renderers: Vec::new(), 38 | render_layers: Vec::new(), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /game_state/src/state/simulation_state.rs: -------------------------------------------------------------------------------- 1 | use nphysics3d::math::Vector; 2 | use nphysics3d::world::{DefaultGeometricalWorld, DefaultMechanicalWorld}; 3 | 4 | pub struct SimulationState { 5 | pub geometrical_world: DefaultGeometricalWorld, 6 | pub mechanical_world: DefaultMechanicalWorld, 7 | } 8 | 9 | impl Default for SimulationState { 10 | fn default() -> Self { 11 | SimulationState { 12 | geometrical_world: DefaultGeometricalWorld::new(), 13 | mechanical_world: DefaultMechanicalWorld::new(Vector::new(0.0, 1.0, 0.0)), 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /game_state/src/state/ui_state.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | use crate::ui::events::UIEvent; 4 | 5 | #[derive(Default)] 6 | pub struct UIState { 7 | pub pending_ui_events: VecDeque, 8 | //pub scene: SceneGraph 9 | } 10 | -------------------------------------------------------------------------------- /game_state/src/thing/mod.rs: -------------------------------------------------------------------------------- 1 | use std::sync::{Arc, Mutex}; 2 | use std::time::Duration; 3 | 4 | use nalgebra::{Matrix4, Perspective3, Scalar, Vector3}; 5 | 6 | use crate::{create_next_identity, model, Identifyable, Identity}; 7 | 8 | #[derive(Copy, Clone)] 9 | pub enum FacetIndex { 10 | Physical(usize), // does it have mass? 11 | Health(usize), // can it be hurt? die? 12 | Camera(usize), 13 | Model(usize), 14 | // Input(usize), 15 | // Network(usize), 16 | // Pathing(usize), // finding it's way around 17 | // Dialogue(usize), // can this entity be talked with? 18 | // AI(usize), 19 | } 20 | 21 | pub struct ModelInstanceFacet 22 | where 23 | U: Scalar, 24 | { 25 | pub transform: Matrix4, 26 | pub model: Arc, 27 | } 28 | 29 | pub struct HealthFacet { 30 | pub hp: u32, 31 | } 32 | 33 | impl HealthFacet { 34 | pub fn new(hp: u32) -> Self { 35 | HealthFacet { hp } 36 | } 37 | pub fn take_dmg(&mut self, dmg: u32) { 38 | if dmg > self.hp { 39 | self.hp = 0; 40 | } else { 41 | self.hp -= dmg; 42 | } 43 | } 44 | pub fn is_alive(&self) -> bool { 45 | self.hp > 0 46 | } 47 | } 48 | 49 | pub enum Shape { 50 | Box { width: f32, height: f32, depth: f32 }, 51 | Cone { radius: f32, height: f32 }, 52 | Cylinder { radius: f32, height: f32 }, 53 | Sphere { radius: f32 }, 54 | } 55 | 56 | pub struct PhysicalFacet { 57 | pub body: Shape, 58 | pub mass: f32, 59 | pub linear_velocity: Vector3, 60 | pub angular_velocity: Vector3, // is this sufficient for angular velocity? durrrrr 61 | pub position: Vector3, 62 | } 63 | 64 | pub struct CameraFacet { 65 | // TODO: pos and rotation should be part of PhysicalFacet 66 | pub pos: Vector3, 67 | pub pitch: f32, 68 | pub yaw: f32, 69 | 70 | _dirty: bool, 71 | pub rotation_speed: f32, 72 | pub movement_speed: f32, 73 | 74 | pub view: Matrix4, 75 | pub perspective: Perspective3, 76 | pub movement_dir: Option, 77 | } 78 | 79 | #[derive(Debug)] 80 | pub enum Direction { 81 | Up, 82 | Down, 83 | Left, 84 | Right, 85 | Forward, 86 | Backward, 87 | } 88 | 89 | impl CameraFacet { 90 | pub fn new(pos: Vector3, pitch: f32, yaw: f32) -> Self { 91 | let mut c = CameraFacet { 92 | pos, 93 | pitch, 94 | yaw, 95 | rotation_speed: 1.0, 96 | movement_speed: 1.0, 97 | movement_dir: None, 98 | _dirty: false, 99 | view: Matrix4::::identity(), 100 | 101 | // TODO fix default perspective values 102 | perspective: Perspective3::::new( 103 | 1.7, //aspect 104 | 0.75, //fovy 105 | 0.0, // near 106 | 1000.0, //far 107 | ), 108 | }; 109 | c.update_view_matrix(); 110 | c 111 | } 112 | 113 | pub fn set_perspective(&mut self, fov: f32, aspect: f32, near: f32, far: f32) { 114 | self.perspective = Perspective3::::new(aspect, fov, near, far); 115 | } 116 | 117 | pub fn update_aspect_ratio(&mut self, aspect: f32) { 118 | self.perspective.set_aspect(aspect); 119 | } 120 | 121 | pub fn forward(&self) -> Vector3 { 122 | let rx = self.pitch; 123 | let ry = self.yaw; 124 | Vector3::new(-(rx.cos()) * ry.sin(), rx.sin(), rx.cos() * ry.cos()).normalize() 125 | } 126 | 127 | pub fn right(&self) -> Vector3 { 128 | let y = Vector3::new(1.0, 0.0, 0.0); 129 | let forward = self.forward(); 130 | let cross = y.cross(&forward); 131 | cross.normalize() 132 | } 133 | 134 | pub fn up(&self) -> Vector3 { 135 | let x = Vector3::new(0.0, 1.0, 0.0); 136 | x.cross(&self.forward()).normalize() 137 | } 138 | 139 | pub fn update(&mut self, dt: &Duration) { 140 | let amount = (dt.as_millis() as f64 / 100.0) as f32; 141 | if let Some(move_dir) = &self.movement_dir { 142 | let m = self.movement_speed * amount; 143 | let d = match move_dir { 144 | Direction::Forward => self.forward(), 145 | Direction::Backward => -self.forward(), 146 | Direction::Right => self.right(), 147 | Direction::Left => -self.right(), 148 | Direction::Up => self.up(), 149 | Direction::Down => -self.up(), 150 | }; 151 | self.pos += d * m; 152 | } 153 | self.update_view_matrix(); 154 | } 155 | 156 | pub fn update_view_matrix(&mut self) { 157 | let rot = Matrix4::from_euler_angles(self.pitch, self.yaw, 0.0); 158 | let trans = Matrix4::new_translation(&self.pos); 159 | self.view = trans * rot; 160 | self._dirty = true; 161 | } 162 | } 163 | 164 | // TODO implement the rest of the facets 165 | // the main idea here is to construct contiguous areas in memory for different facets 166 | // this is a premature optimization for the Thing/Facet system in general to avoid losing cache 167 | // coherency whilst traversing a series of objects. Probably we want to integrate concurrency 168 | // safety here. 169 | #[derive(Default)] 170 | pub struct WorldFacets { 171 | pub cameras: Vec, 172 | pub models: Vec, 173 | pub physical: Vec, 174 | pub health: Vec, 175 | } 176 | 177 | impl WorldFacets { 178 | pub fn new() -> Self { 179 | Default::default() 180 | } 181 | } 182 | 183 | #[derive(Default)] 184 | pub struct World { 185 | things: Vec>>, 186 | facets: WorldFacets, 187 | } 188 | 189 | impl World { 190 | pub fn new() -> Self { 191 | Default::default() 192 | } 193 | 194 | pub fn start_thing(&mut self) -> ThingBuilder { 195 | ThingBuilder { 196 | world: self, 197 | facets: Vec::new(), 198 | } 199 | } 200 | 201 | pub fn get_things(&self) -> &Vec>> { 202 | &self.things 203 | } 204 | 205 | pub fn get_facets(&mut self) -> &mut WorldFacets { 206 | &mut self.facets 207 | } 208 | 209 | pub fn clear(&mut self) { 210 | self.facets.cameras.clear(); 211 | self.facets.health.clear(); 212 | self.facets.models.clear(); 213 | self.facets.physical.clear(); 214 | } 215 | } 216 | 217 | pub struct ThingBuilder<'a> { 218 | world: &'a mut World, 219 | facets: Vec, 220 | } 221 | 222 | impl<'a> ThingBuilder<'a> { 223 | pub fn with_camera(mut self, camera: CameraFacet) -> Self { 224 | let idx = self.world.facets.cameras.len(); 225 | self.world.facets.cameras.push(camera); 226 | self.facets.push(FacetIndex::Camera(idx)); 227 | self 228 | } 229 | 230 | pub fn with_model(mut self, transform: Matrix4, model: Arc) -> Self { 231 | let idx = self.world.facets.models.len(); 232 | self.world 233 | .facets 234 | .models 235 | .push(ModelInstanceFacet { transform, model }); 236 | self.facets.push(FacetIndex::Model(idx)); 237 | self 238 | } 239 | 240 | pub fn build(self) -> Arc> { 241 | let thing = Thing::new(self.facets); 242 | let a = Arc::new(Mutex::new(thing)); 243 | self.world.things.push(a.clone()); 244 | a 245 | } 246 | } 247 | 248 | pub struct Thing { 249 | pub id: Identity, 250 | pub facets: Vec, // index pointers to WorldFacets' specific fields 251 | } 252 | 253 | impl Thing { 254 | pub fn new(facets: Vec) -> Self { 255 | let id = create_next_identity(); 256 | Thing { id, facets } 257 | } 258 | 259 | pub fn get_camera_fi(&self) -> Option { 260 | self.facets 261 | .iter() 262 | .find(|i| { 263 | if let FacetIndex::Camera(_) = i { 264 | true 265 | } else { 266 | false 267 | } 268 | }) 269 | .cloned() 270 | } 271 | 272 | pub fn get_model_fi(&self) -> Option { 273 | self.facets 274 | .iter() 275 | .find(|i| { 276 | if let FacetIndex::Camera(_) = i { 277 | true 278 | } else { 279 | false 280 | } 281 | }) 282 | .cloned() 283 | } 284 | } 285 | 286 | impl Identifyable for Thing { 287 | fn identify(&self) -> u64 { 288 | self.id 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /game_state/src/tree.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::collections::VecDeque; 3 | use std::fmt; 4 | use std::rc::{Rc, Weak}; 5 | use std::sync::atomic::{AtomicUsize, Ordering}; 6 | 7 | type NodeMut = RefCell>; 8 | pub type RcNode = Rc>; 9 | pub type WeakNode = Weak>; 10 | 11 | static GLOBAL_NODE_ID: AtomicUsize = AtomicUsize::new(0); 12 | 13 | pub trait NodeVisitor { 14 | fn visit ()>(&mut self, func: F); 15 | fn has_next(&self) -> bool; 16 | } 17 | 18 | #[derive(Default)] 19 | pub struct Node { 20 | pub id: usize, 21 | parent: Option>, 22 | children: Vec>, 23 | pub data: T, 24 | } 25 | 26 | pub struct BreadthFirstIterator { 27 | queue: VecDeque>, 28 | } 29 | 30 | impl BreadthFirstIterator { 31 | pub fn new(root: RcNode) -> Self { 32 | let mut queue = VecDeque::new(); 33 | queue.push_back(root); 34 | BreadthFirstIterator { queue } 35 | } 36 | } 37 | 38 | impl Iterator for BreadthFirstIterator { 39 | type Item = (usize, RcNode); 40 | fn next(&mut self) -> Option { 41 | match self.queue.pop_front() { 42 | Some(ref n) => { 43 | for child in n.borrow().children() { 44 | self.queue.push_back(child.clone()); 45 | } 46 | let id = n.borrow().id; 47 | Some((id, n.clone())) 48 | } 49 | None => None, 50 | } 51 | } 52 | } 53 | 54 | pub struct BreadthFirstVisitor { 55 | queue: VecDeque>, 56 | } 57 | 58 | impl BreadthFirstVisitor { 59 | pub fn new(root: RcNode) -> Self { 60 | let mut queue = VecDeque::new(); 61 | queue.push_back(root); 62 | BreadthFirstVisitor { queue } 63 | } 64 | } 65 | 66 | impl NodeVisitor for BreadthFirstVisitor { 67 | fn visit ()>(&mut self, func: F) { 68 | let mut func = func; 69 | if let Some(ref n) = self.queue.pop_front() { 70 | for child in n.borrow().children() { 71 | self.queue.push_back(child.clone()); 72 | } 73 | (func)(&n.borrow().data); 74 | } 75 | } 76 | fn has_next(&self) -> bool { 77 | !self.queue.is_empty() 78 | } 79 | } 80 | 81 | impl Drop for Node { 82 | fn drop(&mut self) { 83 | println!("Dropping node {}", self.id); 84 | } 85 | } 86 | 87 | impl fmt::Display for Node { 88 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 89 | let p = match self.parent { 90 | Some(_) => "*", 91 | None => "*root", 92 | }; 93 | write!(f, "{} ->(id: {})", p, self.id).expect("unable to display node"); 94 | Ok(()) 95 | } 96 | } 97 | 98 | impl Node { 99 | pub fn create(data: T, parent: Option>) -> RcNode { 100 | let prt = match parent { 101 | Some(ref p) => Some(Rc::downgrade(p)), 102 | None => None, 103 | }; 104 | 105 | let node = Rc::new(RefCell::new(Node::new(data, prt))); 106 | 107 | if let Some(ref p) = parent { 108 | p.borrow_mut().add_child(node.clone()); 109 | } 110 | node 111 | } 112 | 113 | pub fn find_root(node: RcNode) -> RcNode { 114 | match node.borrow().parent() { 115 | Some(p) => Node::find_root(p), 116 | None => node.clone(), 117 | } 118 | } 119 | 120 | fn new(data: T, parent: Option>) -> Self { 121 | Node { 122 | id: GLOBAL_NODE_ID.fetch_add(1, Ordering::SeqCst), 123 | parent: match parent { 124 | Some(p) => Some(p), 125 | None => None, 126 | }, 127 | children: Vec::new(), 128 | data, 129 | } 130 | } 131 | 132 | /// Recursively find if this node is a child of another 133 | pub fn is_child_of(this: RcNode, parent: RcNode) -> bool { 134 | match this.borrow().parent() { 135 | Some(p) => { 136 | if p.borrow().id == parent.borrow().id { 137 | true 138 | } else { 139 | Node::is_child_of(p, parent) 140 | } 141 | } 142 | None => false, 143 | } 144 | } 145 | 146 | pub fn reparent(child: RcNode, target: RcNode) -> Result<(), String> { 147 | if child.borrow().id == target.borrow().id { 148 | return Err("Cannot make node a child of itself.".to_string()); 149 | } 150 | if !Node::is_child_of(target.clone(), child.clone()) { 151 | // check for cycles 152 | if let Some(old_parent) = child.borrow().parent() { 153 | old_parent.borrow_mut().remove_child(child.clone()); 154 | } 155 | child.borrow_mut().parent = Some(Rc::downgrade(&target.clone())); 156 | target.borrow_mut().add_child(child); 157 | Ok(()) 158 | } else { 159 | Err("Node cycle detected. Child is a parent of reparent target.".to_string()) 160 | // format for better debug msg 161 | } 162 | } 163 | 164 | pub fn remove_child(&mut self, child: RcNode) { 165 | let mut idx: Option = None; 166 | for i in 0usize..self.children.len() { 167 | let child_id = self.children[i].borrow().id; 168 | if child_id == child.borrow().id { 169 | idx = Some(i); 170 | break; 171 | } 172 | } 173 | if let Some(i) = idx { 174 | self.children.remove(i); 175 | } 176 | } 177 | 178 | pub fn find_child(&self, id: usize) -> Option> { 179 | let option: Option<&RcNode> = self.children.iter().find(|x| x.borrow().id == id); 180 | match option { 181 | Some(obj_ref) => Some(obj_ref.clone()), 182 | None => None, 183 | } 184 | } 185 | 186 | pub fn siblings(&self) -> Option>> { 187 | match self.parent() { 188 | Some(p) => Some( 189 | p.borrow() 190 | .children 191 | .iter() 192 | .filter(|x| x.borrow().id != self.id) 193 | .cloned() 194 | .collect(), 195 | ), 196 | None => None, 197 | } 198 | } 199 | 200 | pub fn children(&self) -> &Vec> { 201 | &self.children 202 | } 203 | 204 | pub fn is_leaf(&self) -> bool { 205 | self.children.is_empty() 206 | } 207 | 208 | // intentionally private for the time being (Node::new() specifies a parent) 209 | fn add_child(&mut self, child: RcNode) { 210 | if self.id != child.borrow().id { 211 | self.children.push(child); 212 | } 213 | } 214 | 215 | pub fn parent(&self) -> Option> { 216 | match self.parent { 217 | Some(ref p) => Some(p.upgrade().unwrap()), 218 | None => None, 219 | } 220 | } 221 | 222 | pub fn debug_draw(&self, lvl: usize) { 223 | if lvl == 0 { 224 | println!("-- Hierarchy Dump --"); 225 | } 226 | let c = if !self.children.is_empty() { 227 | "..." 228 | } else { 229 | ".leaf*" 230 | }; 231 | println!( 232 | "{}{}{}", 233 | (0..lvl).map(|_| "....").collect::(), 234 | self, 235 | c 236 | ); 237 | for child in &self.children { 238 | child.borrow().debug_draw(lvl + 1); 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /game_state/src/ui/events.rs: -------------------------------------------------------------------------------- 1 | use crate::Identity; 2 | 3 | #[derive(Debug, Copy, Clone)] 4 | pub enum UIEvent { 5 | Clicked(Identity), 6 | GainedFocus(Identity), 7 | LeftFocus(Identity), 8 | } 9 | -------------------------------------------------------------------------------- /game_state/src/ui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod view; 2 | pub mod events; -------------------------------------------------------------------------------- /game_state/src/ui/view.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use crate::create_next_identity; 4 | use crate::event::{ArcEventHandler, CopyingEventProducer, EventProducer}; 5 | use crate::input::screen::{ScreenPoint, ScreenRect}; 6 | use crate::ui::events::UIEvent; 7 | use crate::Identifyable; 8 | use crate::Identity; 9 | 10 | pub struct UIView { 11 | pub id: Identity, 12 | pub tag: String, 13 | pub bounds: ScreenRect, 14 | } 15 | impl UIView { 16 | pub fn new(tag: String, bounds: ScreenRect) -> Self { 17 | UIView { 18 | id: create_next_identity(), 19 | tag, 20 | bounds, 21 | } 22 | } 23 | 24 | fn hit_test(&self, point: ScreenPoint) -> bool { 25 | self.bounds.intersects(&point) 26 | } 27 | 28 | pub fn move_to_point(&mut self, point: ScreenPoint) { 29 | self.bounds.x = point.x; 30 | self.bounds.y = point.y; 31 | } 32 | 33 | pub fn tag(&self) -> &str { 34 | &self.tag 35 | } 36 | } 37 | 38 | impl Identifyable for UIView { 39 | fn identify(&self) -> Identity { 40 | self.id 41 | } 42 | } 43 | 44 | pub struct UIWindow { 45 | id: Identity, 46 | pub tag: String, 47 | //TODO: should make the view private 48 | pub view: UIView, 49 | event_producer: CopyingEventProducer, 50 | active_handlers: HashMap>, 51 | } 52 | 53 | impl UIWindow { 54 | pub fn new(tag: String, bounds: ScreenRect) -> Self { 55 | UIWindow { 56 | id: create_next_identity(), 57 | tag: tag.clone(), 58 | view: UIView::new(tag, bounds), 59 | event_producer: CopyingEventProducer::::new(), 60 | active_handlers: HashMap::new(), 61 | } 62 | } 63 | pub fn perform_click(&mut self, p: ScreenPoint) { 64 | if self.view.hit_test(p) { 65 | let event = UIEvent::Clicked(self.id); 66 | self.event_producer.publish(event); 67 | } 68 | } 69 | 70 | pub fn subscribe_click ()>(&mut self, func: F) 71 | where 72 | F: 'static, 73 | { 74 | let event_handler = CopyingEventProducer::::create_handler(func); 75 | let tag = format!("{}_onclick", self.tag); 76 | // Window will own it's handlers: 77 | self.active_handlers 78 | .entry(tag.to_string()) 79 | .or_insert_with(|| event_handler.clone()); 80 | self.event_producer 81 | .add_handler(tag.to_string(), &event_handler); 82 | } 83 | } 84 | 85 | pub struct UIButton { 86 | pub text: UIView, 87 | pub background: UIView, 88 | } 89 | 90 | #[cfg(test)] 91 | mod tests { 92 | 93 | use super::*; 94 | 95 | use std::sync::{Arc, Mutex}; 96 | 97 | #[test] 98 | fn test_window_hit_test() { 99 | let mut window = UIWindow::new("window1".to_string(), ScreenRect::new(10, 10, 20, 20)); 100 | let _generic = UIView::new("dunno".to_string(), ScreenRect::new(5, 5, 5, 5)); 101 | let hit = ScreenPoint::new(15, 15); 102 | let miss = ScreenPoint::new(5, 5); 103 | window.view.move_to_point(hit.clone()); 104 | assert!(window.view.hit_test(hit)); 105 | assert!(!window.view.hit_test(miss)); 106 | } 107 | 108 | #[test] 109 | fn test_window_click() { 110 | let mut window = UIWindow::new("window1".to_string(), ScreenRect::new(10, 10, 20, 20)); 111 | let flag = Arc::new(Mutex::new(0_u32)); 112 | let cflag = flag.clone(); 113 | 114 | window.subscribe_click(move |_ /*event:UIEvent*/| { 115 | *cflag.lock().unwrap() = 1; 116 | }); 117 | 118 | assert!(*flag.lock().unwrap() == 0); 119 | 120 | let point = ScreenPoint::new(15, 15); 121 | window.perform_click(point); 122 | 123 | assert!(*flag.lock().unwrap() == 1); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /game_state/src/utils/fps.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | 3 | pub struct FPS { 4 | num_samples: u32, 5 | frame_count: u32, 6 | last_frame: Instant, 7 | } 8 | 9 | impl FPS { 10 | pub fn new() -> Self { 11 | FPS { 12 | num_samples: 10000, 13 | frame_count: 0, 14 | last_frame: Instant::now(), 15 | } 16 | } 17 | 18 | pub fn update(&mut self) { 19 | self.frame_count = if self.frame_count > self.num_samples { 20 | self.last_frame = Instant::now(); 21 | 0 22 | } else { 23 | self.frame_count + 1 24 | } 25 | } 26 | 27 | pub fn get(&self) -> f32 { 28 | let diff = self.last_frame.elapsed(); 29 | let millis = diff.as_millis(); 30 | self.frame_count as f32 / millis as f32 * 1000 as f32 31 | } 32 | 33 | pub fn count(&self) -> u32 { 34 | self.frame_count 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /game_state/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod fps; 2 | 3 | -------------------------------------------------------------------------------- /game_state/tests/node.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | 4 | use game_state::tree::{BreadthFirstVisitor, Node, NodeVisitor, RcNode}; 5 | 6 | #[test] 7 | fn traverse_nodes() { 8 | let root_ptr = Node::create(0, None); 9 | let child_ptr = Node::create(0, Some(root_ptr.clone())); 10 | let found_child = root_ptr.borrow().find_child(child_ptr.borrow().id); 11 | assert!(found_child.is_some()); 12 | } 13 | 14 | #[test] 15 | fn find_root() { 16 | let root = Node::create(0, None); 17 | let child = Node::create(0, Some(root.clone())); 18 | let found_root = Node::find_root(child.clone()); 19 | assert!(root.borrow().id == found_root.borrow().id); 20 | } 21 | 22 | #[test] 23 | fn is_child_of() { 24 | let root = Node::create(0, None); 25 | let child = Node::create(0, Some(root.clone())); 26 | assert!(Node::is_child_of(child.clone(), root.clone())); 27 | let r = Node::create(0, None); 28 | assert!(!Node::is_child_of(child.clone(), r.clone())); 29 | } 30 | 31 | #[test] 32 | fn reparent() { 33 | let root = Node::create(0, None); 34 | 35 | let child = Node::create(0, Some(root.clone())); 36 | let original_child = root.borrow().find_child(child.borrow().id); 37 | assert!(original_child.is_some()); 38 | 39 | let root2 = Node::create(0, None); 40 | Node::reparent(child.clone(), root2.clone()).unwrap(); 41 | 42 | let found_root = Node::find_root(child.clone()); 43 | assert!(root2.borrow().id == found_root.borrow().id); 44 | 45 | let stale_child = root.borrow().find_child(child.borrow().id); 46 | assert!(stale_child.is_none()); 47 | 48 | let actual_child = root2.borrow().find_child(child.borrow().id); 49 | assert!(actual_child.is_some()); 50 | } 51 | 52 | #[test] 53 | fn is_child_of_reparent() { 54 | let root = Node::create(0, None); 55 | let im = Node::create(0, Some(root.clone())); 56 | let child = Node::create(0, Some(im.clone())); 57 | assert!(Node::is_child_of(child.clone(), im.clone())); 58 | assert!(Node::is_child_of(child.clone(), root.clone())); 59 | 60 | let root2 = Node::create(0, None); 61 | let result = Node::reparent(im.clone(), root2.clone()); 62 | 63 | assert!(result.is_ok()); 64 | assert!(Node::is_child_of(child.clone(), root2.clone())); 65 | } 66 | 67 | #[test] 68 | fn fails_to_reparent_to_self() { 69 | let root = Node::create(0, None); 70 | let result = Node::reparent(root.clone(), root.clone()); 71 | assert!(result.is_err()); 72 | } 73 | 74 | #[test] 75 | fn fails_to_reparent_causing_a_cycle() { 76 | let root = Node::create(0, None); 77 | let _child = Node::create(0, Some(root.clone())); 78 | let sibling = Node::create(0, Some(root.clone())); 79 | 80 | let result = Node::reparent(root.clone(), sibling.clone()); 81 | assert!(result.is_err()); 82 | } 83 | 84 | #[test] 85 | fn siblings_as_expected() { 86 | let root = Node::create(0, None); 87 | let child = Node::create(0, Some(root.clone())); 88 | let sibling = Node::create(0, Some(root.clone())); 89 | 90 | let maybe_siblings = child.borrow().siblings(); 91 | let siblings = maybe_siblings.unwrap(); 92 | assert!(siblings.len() == 1); 93 | assert!(sibling.borrow().id == siblings[0].borrow().id); 94 | } 95 | 96 | #[test] 97 | fn visitor() { 98 | // master branch 99 | let root = Node::create(5u32, None); 100 | let grandparent = Node::create(4, Some(root.clone())); 101 | let parent = Node::create(3, Some(grandparent.clone())); 102 | let child = Node::create(2, Some(parent.clone())); 103 | let grandchild = Node::create(1, Some(child.clone())); 104 | 105 | // misfits. Sibling branch to those in master 106 | let great_aunt = Node::create(4, Some(root.clone())); 107 | let uncle = Node::create(3, Some(great_aunt.clone())); 108 | let cousin = Node::create(2, Some(uncle.clone())); 109 | let _niece = Node::create(1, Some(cousin.clone())); 110 | 111 | struct SummingVisitor { 112 | x: T, 113 | current_node: Option>, 114 | } 115 | impl NodeVisitor for SummingVisitor { 116 | fn visit ()>(&mut self, func: F) { 117 | let mut func = func; 118 | let (val, maybe_parent) = match self.current_node { 119 | Some(ref n) => (n.borrow().data, n.borrow().parent()), 120 | None => (0, None), 121 | }; 122 | self.x += val; 123 | (func)(&self.x); 124 | self.current_node = maybe_parent; 125 | } 126 | fn has_next(&self) -> bool { 127 | let maybe_parent = match self.current_node { 128 | Some(ref n) => n.borrow().parent(), 129 | None => None, 130 | }; 131 | maybe_parent.is_some() 132 | } 133 | } 134 | 135 | let mut v = SummingVisitor { 136 | x: 0, 137 | current_node: Some(grandchild.clone()), 138 | }; 139 | 140 | while v.has_next() { 141 | v.visit(|x| assert!(*x > 0)); 142 | } 143 | 144 | assert_eq!(v.x, 10); 145 | } 146 | 147 | #[test] 148 | fn breadth_first_visitor() { 149 | // master branch 150 | let root = Node::create(5u32, None); 151 | let grandparent = Node::create(4, Some(root.clone())); 152 | let parent = Node::create(3, Some(grandparent.clone())); 153 | let child = Node::create(2, Some(parent.clone())); 154 | let _grandchild = Node::create(1, Some(child.clone())); 155 | 156 | // misfits. Sibling branch to those in master 157 | let great_aunt = Node::create(4, Some(root.clone())); 158 | let uncle = Node::create(3, Some(great_aunt.clone())); 159 | let cousin = Node::create(2, Some(uncle.clone())); 160 | let _niece = Node::create(1, Some(cousin.clone())); 161 | 162 | let mut visitor = BreadthFirstVisitor::new(root.clone()); 163 | 164 | let mut counter = 0; 165 | let mut loop_ctr = 0; 166 | while visitor.has_next() { 167 | loop_ctr += 1; 168 | visitor.visit(|x| counter += *x); 169 | } 170 | assert_eq!(loop_ctr, 9); 171 | assert_eq!(counter, 25); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /mod_asset_loader/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_asset_loader" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | dynamic_lib = [] 11 | 12 | [lib] 13 | name = "mod_asset_loader" 14 | crate-type=["dylib"] 15 | 16 | [dependencies] 17 | 18 | [dependencies.game_state] 19 | path = "../game_state" 20 | -------------------------------------------------------------------------------- /mod_asset_loader/README.md: -------------------------------------------------------------------------------- 1 | # `mod_asset_loader` 2 | 3 | this module is intended for loading/unloading assets from the State -------------------------------------------------------------------------------- /mod_asset_loader/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | use std::time::Duration; 3 | 4 | // TODO: switch to nalgebra 5 | use game_state::nalgebra::{Matrix4, Vector3}; 6 | 7 | use game_state::model::Model; 8 | use game_state::state::ModelAccess; 9 | use game_state::state::RenderLayerAccess; 10 | use game_state::state::SceneGraph; 11 | use game_state::state::State; 12 | use game_state::state::WorldAccess; 13 | use game_state::thing::CameraFacet; 14 | use game_state::tree::Node; 15 | 16 | #[no_mangle] 17 | pub extern "C" fn mod_asset_loader_load(state: &mut State) { 18 | assert!(state.get_render_layers().is_empty()); 19 | 20 | let origin = Vector3::new(0.0, 0.0, 0.0); 21 | let mx = Matrix4::new_translation(&origin) * Matrix4::new_scaling(1.0); 22 | 23 | let model_path = "assets/models/plane.obj"; 24 | println!(" loading model: {}", model_path); 25 | let helper = Model::load(model_path, mx).unwrap().pop().unwrap(); 26 | 27 | let am = Arc::new(helper); 28 | state.add_model(am.clone()); 29 | 30 | let world = state.get_world(); 31 | // build the actual entity within the world 32 | let _camera = world 33 | .start_thing() 34 | .with_camera(CameraFacet::new( 35 | Vector3::new(0.0, 0.0, -2.0), // pos 36 | -1.5, // pitch 37 | 0.0, // yaw 38 | )) 39 | .build(); 40 | 41 | let _helper_cube = world.start_thing().with_model(mx, am.clone()).build(); 42 | 43 | let root = Node::create(None, None); 44 | 45 | // TODO make this tree api better... currently returns the node, instead make a builder? 46 | // or maybe load from a file format (yaml?) 47 | let _ = Node::create(None, Some(root.clone())); 48 | let helpers = Node::create(None, Some(root.clone())); 49 | let _ = Node::create(Some(am.clone()), Some(helpers.clone())); 50 | let _ = Node::create(Some(am), Some(helpers.clone())); 51 | 52 | // NOTE: there's some index-mirroring happening here, we probably want to associate somehow 53 | // other than this - it's going to be easy to get wrong 54 | state.add_render_layer(Arc::new(SceneGraph { root })); 55 | } 56 | 57 | #[no_mangle] 58 | pub extern "C" fn mod_asset_loader_update(_state: &mut State, _dt: &Duration) { 59 | // 60 | // this module might look for unused assets, or requests for loading new ones? 61 | // for instance, instead of blindly loading an asset and pushing it into state, we COULD be loading files 62 | // in a multithreaded context, pushing them in on this thread when we are ticked 63 | // 64 | } 65 | 66 | #[no_mangle] 67 | pub extern "C" fn mod_asset_loader_unload(state: &mut State) { 68 | state.clear_render_layers(); 69 | } 70 | -------------------------------------------------------------------------------- /mod_dummy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_dummy" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | dynamic_lib = [] 11 | 12 | [lib] 13 | name = "mod_dummy" 14 | crate-type=["dylib"] 15 | 16 | [dependencies] 17 | 18 | [dependencies.game_state] 19 | path = "../game_state" 20 | -------------------------------------------------------------------------------- /mod_dummy/README.md: -------------------------------------------------------------------------------- 1 | # `mod_dummy` 2 | 3 | This is just a dummy lib, showing how to have a multi-step simulation with separate libraries for each 4 | - it's purpose is a starting template for new modules 5 | -------------------------------------------------------------------------------- /mod_dummy/build.rs: -------------------------------------------------------------------------------- 1 | fn main() {} 2 | -------------------------------------------------------------------------------- /mod_dummy/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use game_state::state::State; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn mod_dummy_load(state: &mut State) {} 7 | 8 | #[no_mangle] 9 | pub extern "C" fn mod_dummy_update(state: &mut State, dt: &Duration) {} 10 | 11 | #[no_mangle] 12 | pub extern "C" fn mod_dummy_unload(state: &mut State) {} 13 | -------------------------------------------------------------------------------- /mod_gamepad/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_gamepad" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | dynamic_lib = [] 11 | 12 | [lib] 13 | name = "mod_gamepad" 14 | crate-type=["dylib"] 15 | 16 | [dependencies] 17 | gilrs = "0.6" 18 | 19 | [dependencies.game_state] 20 | path = "../game_state" 21 | -------------------------------------------------------------------------------- /mod_gamepad/README.md: -------------------------------------------------------------------------------- 1 | # `mod_gamepad` 2 | Unfortunately, this mod cannot be reloaded at runtime. It's isolated as an external InputSource to prevent segfaults reloading mod_input 3 | -------------------------------------------------------------------------------- /mod_gamepad/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::time::Duration; 3 | 4 | use gilrs::{Axis, Button, Event, EventType, Gilrs}; 5 | 6 | use game_state::input::events::{DeviceId, InputEvent, JoyAxis, JoyButton}; 7 | //use game_state::input::InputSource; 8 | use game_state::state::{InputAccess, State}; 9 | use game_state::thing::Direction; 10 | use game_state::{Identifyable, Identity}; 11 | 12 | struct GamepadInput { 13 | id: Identity, 14 | gilrs: Gilrs, 15 | } 16 | 17 | impl GamepadInput { 18 | pub fn new() -> Self { 19 | GamepadInput { 20 | id: game_state::create_next_identity(), 21 | gilrs: Gilrs::new().unwrap(), // TODO: bubble error 22 | } 23 | } 24 | } 25 | 26 | impl Identifyable for GamepadInput { 27 | fn identify(&self) -> Identity { 28 | self.id 29 | } 30 | } 31 | 32 | fn convert_button(b: &Button) -> JoyButton { 33 | match b { 34 | Button::South => JoyButton::South, 35 | Button::East => JoyButton::East, 36 | Button::North => JoyButton::North, 37 | Button::West => JoyButton::West, 38 | Button::C => JoyButton::C, 39 | Button::Z => JoyButton::Z, 40 | Button::LeftTrigger => JoyButton::LeftTrigger, 41 | Button::LeftTrigger2 => JoyButton::LeftTrigger2, 42 | Button::RightTrigger => JoyButton::RightTrigger, 43 | Button::RightTrigger2 => JoyButton::RightTrigger2, 44 | Button::Select => JoyButton::Select, 45 | Button::Start => JoyButton::Start, 46 | Button::Mode => JoyButton::Mode, 47 | Button::LeftThumb => JoyButton::LeftThumb, 48 | Button::RightThumb => JoyButton::RightThumb, 49 | Button::DPadUp => JoyButton::DPadUp, 50 | Button::DPadDown => JoyButton::DPadDown, 51 | Button::DPadLeft => JoyButton::DPadLeft, 52 | Button::DPadRight => JoyButton::DPadRight, 53 | Button::Unknown => JoyButton::Unknown, 54 | } 55 | } 56 | 57 | fn convert_axis(a: &Axis) -> JoyAxis { 58 | match a { 59 | Axis::LeftStickX => JoyAxis::LeftStickX, 60 | Axis::LeftStickY => JoyAxis::LeftStickY, 61 | Axis::LeftZ => JoyAxis::LeftZ, 62 | Axis::RightStickX => JoyAxis::RightStickX, 63 | Axis::RightStickY => JoyAxis::RightStickY, 64 | Axis::RightZ => JoyAxis::RightZ, 65 | Axis::DPadX => JoyAxis::DPadX, 66 | Axis::DPadY => JoyAxis::DPadY, 67 | Axis::Unknown => JoyAxis::Unknown, 68 | } 69 | } 70 | 71 | /* 72 | // TODO: implement from instead 73 | // TODO: VecDeque -> (Event Channel) 74 | impl InputSource for GamepadInput { 75 | fn get_input_events(&mut self) -> VecDeque { 76 | let mut converted_events = VecDeque::new(); 77 | //... 78 | while let Some(Event { id, event, time }) = self.gilrs.next_event() { 79 | let event = match event { 80 | EventType::ButtonPressed(button, _code) => { 81 | let b = convert_button(&button); 82 | converted_events.push_back(InputEvent::JoyButtonDown(self.identify(), id, b)); 83 | } 84 | EventType::ButtonRepeated(button, _code) => { 85 | let b = convert_button(&button); 86 | converted_events.push_back(InputEvent::JoyButtonRepeated( 87 | self.identify(), 88 | id, 89 | b, 90 | )); 91 | } 92 | EventType::ButtonReleased(button, _code) => { 93 | let b = convert_button(&button); 94 | converted_events.push_back(InputEvent::JoyButtonUp(self.identify(), id, b)); 95 | } 96 | EventType::ButtonChanged(button, value, _code) => { 97 | let b = convert_button(&button); 98 | converted_events.push_back(InputEvent::JoyButtonChanged( 99 | self.identify(), 100 | id, 101 | b, 102 | value, 103 | )); 104 | } 105 | EventType::AxisChanged(axis, value, _code) => { 106 | let a = convert_axis(&axis); 107 | converted_events.push_back(InputEvent::JoyAxisChanged( 108 | self.identify(), 109 | id, 110 | a, 111 | value, 112 | )); 113 | } 114 | EventType::Connected => { 115 | converted_events.push_back(InputEvent::JoyConnected(self.identify(), id)); 116 | } 117 | EventType::Disconnected => { 118 | converted_events.push_back(InputEvent::JoyDisconnected(self.identify(), id)); 119 | } 120 | EventType::Dropped => { 121 | converted_events.push_back(InputEvent::JoyEventDropped(self.identify(), id)); 122 | } 123 | }; 124 | } 125 | converted_events 126 | } 127 | } 128 | */ 129 | 130 | #[no_mangle] 131 | pub extern "C" fn mod_gamepad_load(state: &mut State) { 132 | /* let gamepad_input = GamepadInput::new(); 133 | let gamepad_input = Box::new(gamepad_input) as Box; 134 | state.add_input_source(gamepad_input); 135 | */ 136 | } 137 | 138 | #[no_mangle] 139 | pub extern "C" fn mod_gamepad_update(state: &mut State, dt: &Duration) {} 140 | 141 | #[no_mangle] 142 | pub extern "C" fn mod_gamepad_unload(state: &mut State) { 143 | unimplemented!() 144 | } 145 | -------------------------------------------------------------------------------- /mod_input/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "adler" 5 | version = "1.0.2" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 8 | 9 | [[package]] 10 | name = "adler32" 11 | version = "1.2.0" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 14 | 15 | [[package]] 16 | name = "approx" 17 | version = "0.4.0" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" 20 | dependencies = [ 21 | "num-traits", 22 | ] 23 | 24 | [[package]] 25 | name = "arrayvec" 26 | version = "0.4.11" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" 29 | dependencies = [ 30 | "nodrop", 31 | ] 32 | 33 | [[package]] 34 | name = "autocfg" 35 | version = "0.1.6" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" 38 | 39 | [[package]] 40 | name = "autocfg" 41 | version = "1.0.0" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 44 | 45 | [[package]] 46 | name = "base-x" 47 | version = "0.2.6" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" 50 | 51 | [[package]] 52 | name = "bitflags" 53 | version = "1.2.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 56 | 57 | [[package]] 58 | name = "bumpalo" 59 | version = "3.1.2" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" 62 | 63 | [[package]] 64 | name = "bytemuck" 65 | version = "1.5.1" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" 68 | 69 | [[package]] 70 | name = "byteorder" 71 | version = "1.3.2" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" 74 | 75 | [[package]] 76 | name = "cfg-if" 77 | version = "0.1.10" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 80 | 81 | [[package]] 82 | name = "cfg-if" 83 | version = "1.0.0" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 86 | 87 | [[package]] 88 | name = "color_quant" 89 | version = "1.1.0" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 92 | 93 | [[package]] 94 | name = "crc32fast" 95 | version = "1.2.1" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 98 | dependencies = [ 99 | "cfg-if 1.0.0", 100 | ] 101 | 102 | [[package]] 103 | name = "crossbeam-deque" 104 | version = "0.6.3" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" 107 | dependencies = [ 108 | "crossbeam-epoch", 109 | "crossbeam-utils", 110 | ] 111 | 112 | [[package]] 113 | name = "crossbeam-epoch" 114 | version = "0.7.2" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" 117 | dependencies = [ 118 | "arrayvec", 119 | "cfg-if 0.1.10", 120 | "crossbeam-utils", 121 | "lazy_static", 122 | "memoffset", 123 | "scopeguard", 124 | ] 125 | 126 | [[package]] 127 | name = "crossbeam-queue" 128 | version = "0.1.2" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" 131 | dependencies = [ 132 | "crossbeam-utils", 133 | ] 134 | 135 | [[package]] 136 | name = "crossbeam-utils" 137 | version = "0.6.6" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 140 | dependencies = [ 141 | "cfg-if 0.1.10", 142 | "lazy_static", 143 | ] 144 | 145 | [[package]] 146 | name = "deflate" 147 | version = "0.8.6" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" 150 | dependencies = [ 151 | "adler32", 152 | "byteorder", 153 | ] 154 | 155 | [[package]] 156 | name = "discard" 157 | version = "1.0.4" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 160 | 161 | [[package]] 162 | name = "downcast-rs" 163 | version = "1.1.1" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" 166 | 167 | [[package]] 168 | name = "either" 169 | version = "1.5.2" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" 172 | 173 | [[package]] 174 | name = "fixedbitset" 175 | version = "0.2.0" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" 178 | 179 | [[package]] 180 | name = "futures" 181 | version = "0.3.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" 184 | dependencies = [ 185 | "futures-channel", 186 | "futures-core", 187 | "futures-executor", 188 | "futures-io", 189 | "futures-sink", 190 | "futures-task", 191 | "futures-util", 192 | ] 193 | 194 | [[package]] 195 | name = "futures-channel" 196 | version = "0.3.1" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" 199 | dependencies = [ 200 | "futures-core", 201 | "futures-sink", 202 | ] 203 | 204 | [[package]] 205 | name = "futures-core" 206 | version = "0.3.1" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" 209 | 210 | [[package]] 211 | name = "futures-executor" 212 | version = "0.3.1" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" 215 | dependencies = [ 216 | "futures-core", 217 | "futures-task", 218 | "futures-util", 219 | ] 220 | 221 | [[package]] 222 | name = "futures-io" 223 | version = "0.3.1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" 226 | 227 | [[package]] 228 | name = "futures-macro" 229 | version = "0.3.1" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" 232 | dependencies = [ 233 | "proc-macro-hack", 234 | "proc-macro2", 235 | "quote", 236 | "syn", 237 | ] 238 | 239 | [[package]] 240 | name = "futures-sink" 241 | version = "0.3.1" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" 244 | 245 | [[package]] 246 | name = "futures-task" 247 | version = "0.3.1" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" 250 | 251 | [[package]] 252 | name = "futures-util" 253 | version = "0.3.1" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" 256 | dependencies = [ 257 | "futures-channel", 258 | "futures-core", 259 | "futures-io", 260 | "futures-macro", 261 | "futures-sink", 262 | "futures-task", 263 | "memchr", 264 | "pin-utils", 265 | "proc-macro-hack", 266 | "proc-macro-nested", 267 | "slab", 268 | ] 269 | 270 | [[package]] 271 | name = "game_state" 272 | version = "0.2.0" 273 | dependencies = [ 274 | "futures", 275 | "image", 276 | "nalgebra", 277 | "nom-obj", 278 | "nphysics3d", 279 | "sdl2", 280 | "serde", 281 | ] 282 | 283 | [[package]] 284 | name = "generational-arena" 285 | version = "0.2.7" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "0e40d0cee2e2fb4fba18b55a27bf96faf49fa86d49f178695bd3bf4500b156b4" 288 | dependencies = [ 289 | "cfg-if 0.1.10", 290 | ] 291 | 292 | [[package]] 293 | name = "gif" 294 | version = "0.11.2" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" 297 | dependencies = [ 298 | "color_quant", 299 | "weezl", 300 | ] 301 | 302 | [[package]] 303 | name = "hashbrown" 304 | version = "0.9.1" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 307 | 308 | [[package]] 309 | name = "image" 310 | version = "0.23.14" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" 313 | dependencies = [ 314 | "bytemuck", 315 | "byteorder", 316 | "color_quant", 317 | "gif", 318 | "jpeg-decoder", 319 | "num-iter", 320 | "num-rational", 321 | "num-traits", 322 | "png", 323 | "scoped_threadpool", 324 | "tiff", 325 | ] 326 | 327 | [[package]] 328 | name = "indexmap" 329 | version = "1.6.2" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" 332 | dependencies = [ 333 | "autocfg 1.0.0", 334 | "hashbrown", 335 | ] 336 | 337 | [[package]] 338 | name = "instant" 339 | version = "0.1.2" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "6c346c299e3fe8ef94dc10c2c0253d858a69aac1245157a3bf4125915d528caf" 342 | dependencies = [ 343 | "stdweb", 344 | "time", 345 | ] 346 | 347 | [[package]] 348 | name = "itoa" 349 | version = "0.4.5" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 352 | 353 | [[package]] 354 | name = "jpeg-decoder" 355 | version = "0.1.22" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" 358 | dependencies = [ 359 | "rayon", 360 | ] 361 | 362 | [[package]] 363 | name = "lazy_static" 364 | version = "1.4.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 367 | 368 | [[package]] 369 | name = "libc" 370 | version = "0.2.94" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" 373 | 374 | [[package]] 375 | name = "log" 376 | version = "0.4.8" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 379 | dependencies = [ 380 | "cfg-if 0.1.10", 381 | ] 382 | 383 | [[package]] 384 | name = "matrixmultiply" 385 | version = "0.3.1" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "5a8a15b776d9dfaecd44b03c5828c2199cddff5247215858aac14624f8d6b741" 388 | dependencies = [ 389 | "rawpointer", 390 | ] 391 | 392 | [[package]] 393 | name = "memchr" 394 | version = "2.2.1" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" 397 | 398 | [[package]] 399 | name = "memoffset" 400 | version = "0.5.1" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" 403 | dependencies = [ 404 | "rustc_version", 405 | ] 406 | 407 | [[package]] 408 | name = "miniz_oxide" 409 | version = "0.3.7" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 412 | dependencies = [ 413 | "adler32", 414 | ] 415 | 416 | [[package]] 417 | name = "miniz_oxide" 418 | version = "0.4.4" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 421 | dependencies = [ 422 | "adler", 423 | "autocfg 1.0.0", 424 | ] 425 | 426 | [[package]] 427 | name = "mod_input" 428 | version = "0.1.0" 429 | dependencies = [ 430 | "game_state", 431 | ] 432 | 433 | [[package]] 434 | name = "nalgebra" 435 | version = "0.26.2" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "476d1d59fe02fe54c86356e91650cd892f392782a1cb9fc524ec84f7aa9e1d06" 438 | dependencies = [ 439 | "approx", 440 | "matrixmultiply", 441 | "num-complex", 442 | "num-rational", 443 | "num-traits", 444 | "simba", 445 | "typenum", 446 | ] 447 | 448 | [[package]] 449 | name = "ncollide3d" 450 | version = "0.29.0" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "57e1b8b0e8696557b00224e92289ad279c7c12679a904bdc640be5c3eabdaa36" 453 | dependencies = [ 454 | "approx", 455 | "bitflags", 456 | "downcast-rs", 457 | "either", 458 | "nalgebra", 459 | "num-traits", 460 | "petgraph", 461 | "simba", 462 | "slab", 463 | "slotmap", 464 | "smallvec", 465 | ] 466 | 467 | [[package]] 468 | name = "nodrop" 469 | version = "0.1.13" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" 472 | 473 | [[package]] 474 | name = "nom" 475 | version = "2.2.1" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff" 478 | 479 | [[package]] 480 | name = "nom-obj" 481 | version = "0.2.0" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "c0a203a8b25ac1d7a07ba403bce1119f90918c7d928db59ed65181bdf2a2841b" 484 | dependencies = [ 485 | "nom", 486 | ] 487 | 488 | [[package]] 489 | name = "nphysics3d" 490 | version = "0.21.0" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "6994fb4f4c5e2d1fc4d9507213982a80f71587d77900e9ba0e07fc50762322be" 493 | dependencies = [ 494 | "approx", 495 | "bitflags", 496 | "downcast-rs", 497 | "either", 498 | "generational-arena", 499 | "instant", 500 | "lazy_static", 501 | "nalgebra", 502 | "ncollide3d", 503 | "num-traits", 504 | "simba", 505 | "slotmap", 506 | "smallvec", 507 | "stdweb", 508 | ] 509 | 510 | [[package]] 511 | name = "num-complex" 512 | version = "0.3.1" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" 515 | dependencies = [ 516 | "num-traits", 517 | ] 518 | 519 | [[package]] 520 | name = "num-integer" 521 | version = "0.1.42" 522 | source = "registry+https://github.com/rust-lang/crates.io-index" 523 | checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" 524 | dependencies = [ 525 | "autocfg 1.0.0", 526 | "num-traits", 527 | ] 528 | 529 | [[package]] 530 | name = "num-iter" 531 | version = "0.1.39" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" 534 | dependencies = [ 535 | "autocfg 0.1.6", 536 | "num-integer", 537 | "num-traits", 538 | ] 539 | 540 | [[package]] 541 | name = "num-rational" 542 | version = "0.3.2" 543 | source = "registry+https://github.com/rust-lang/crates.io-index" 544 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 545 | dependencies = [ 546 | "autocfg 1.0.0", 547 | "num-integer", 548 | "num-traits", 549 | ] 550 | 551 | [[package]] 552 | name = "num-traits" 553 | version = "0.2.11" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" 556 | dependencies = [ 557 | "autocfg 1.0.0", 558 | ] 559 | 560 | [[package]] 561 | name = "num_cpus" 562 | version = "1.10.1" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" 565 | dependencies = [ 566 | "libc", 567 | ] 568 | 569 | [[package]] 570 | name = "paste" 571 | version = "1.0.5" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" 574 | 575 | [[package]] 576 | name = "petgraph" 577 | version = "0.5.1" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" 580 | dependencies = [ 581 | "fixedbitset", 582 | "indexmap", 583 | ] 584 | 585 | [[package]] 586 | name = "pin-utils" 587 | version = "0.1.0-alpha.4" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" 590 | 591 | [[package]] 592 | name = "png" 593 | version = "0.16.8" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" 596 | dependencies = [ 597 | "bitflags", 598 | "crc32fast", 599 | "deflate", 600 | "miniz_oxide 0.3.7", 601 | ] 602 | 603 | [[package]] 604 | name = "proc-macro-hack" 605 | version = "0.5.11" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" 608 | dependencies = [ 609 | "proc-macro2", 610 | "quote", 611 | "syn", 612 | ] 613 | 614 | [[package]] 615 | name = "proc-macro-nested" 616 | version = "0.1.3" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" 619 | 620 | [[package]] 621 | name = "proc-macro2" 622 | version = "1.0.7" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" 625 | dependencies = [ 626 | "unicode-xid", 627 | ] 628 | 629 | [[package]] 630 | name = "quote" 631 | version = "1.0.2" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 634 | dependencies = [ 635 | "proc-macro2", 636 | ] 637 | 638 | [[package]] 639 | name = "rawpointer" 640 | version = "0.2.1" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" 643 | 644 | [[package]] 645 | name = "rayon" 646 | version = "1.1.0" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" 649 | dependencies = [ 650 | "crossbeam-deque", 651 | "either", 652 | "rayon-core", 653 | ] 654 | 655 | [[package]] 656 | name = "rayon-core" 657 | version = "1.5.0" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" 660 | dependencies = [ 661 | "crossbeam-deque", 662 | "crossbeam-queue", 663 | "crossbeam-utils", 664 | "lazy_static", 665 | "num_cpus", 666 | ] 667 | 668 | [[package]] 669 | name = "redox_syscall" 670 | version = "0.1.56" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 673 | 674 | [[package]] 675 | name = "rustc_version" 676 | version = "0.2.3" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 679 | dependencies = [ 680 | "semver", 681 | ] 682 | 683 | [[package]] 684 | name = "ryu" 685 | version = "1.0.2" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" 688 | 689 | [[package]] 690 | name = "scoped_threadpool" 691 | version = "0.1.9" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 694 | 695 | [[package]] 696 | name = "scopeguard" 697 | version = "1.0.0" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 700 | 701 | [[package]] 702 | name = "sdl2" 703 | version = "0.34.5" 704 | source = "registry+https://github.com/rust-lang/crates.io-index" 705 | checksum = "deecbc3fa9460acff5a1e563e05cb5f31bba0aa0c214bb49a43db8159176d54b" 706 | dependencies = [ 707 | "bitflags", 708 | "lazy_static", 709 | "libc", 710 | "sdl2-sys", 711 | ] 712 | 713 | [[package]] 714 | name = "sdl2-sys" 715 | version = "0.34.5" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "41a29aa21f175b5a41a6e26da572d5e5d1ee5660d35f9f9d0913e8a802098f74" 718 | dependencies = [ 719 | "cfg-if 0.1.10", 720 | "libc", 721 | "version-compare", 722 | ] 723 | 724 | [[package]] 725 | name = "semver" 726 | version = "0.9.0" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 729 | dependencies = [ 730 | "semver-parser", 731 | ] 732 | 733 | [[package]] 734 | name = "semver-parser" 735 | version = "0.7.0" 736 | source = "registry+https://github.com/rust-lang/crates.io-index" 737 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 738 | 739 | [[package]] 740 | name = "serde" 741 | version = "1.0.99" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" 744 | 745 | [[package]] 746 | name = "serde_derive" 747 | version = "1.0.104" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" 750 | dependencies = [ 751 | "proc-macro2", 752 | "quote", 753 | "syn", 754 | ] 755 | 756 | [[package]] 757 | name = "serde_json" 758 | version = "1.0.45" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "eab8f15f15d6c41a154c1b128a22f2dfabe350ef53c40953d84e36155c91192b" 761 | dependencies = [ 762 | "itoa", 763 | "ryu", 764 | "serde", 765 | ] 766 | 767 | [[package]] 768 | name = "sha1" 769 | version = "0.6.0" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 772 | 773 | [[package]] 774 | name = "simba" 775 | version = "0.4.0" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "5132a955559188f3d13c9ba831e77c802ddc8782783f050ed0c52f5988b95f4c" 778 | dependencies = [ 779 | "approx", 780 | "num-complex", 781 | "num-traits", 782 | "paste", 783 | ] 784 | 785 | [[package]] 786 | name = "slab" 787 | version = "0.4.2" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 790 | 791 | [[package]] 792 | name = "slotmap" 793 | version = "1.0.3" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "585cd5dffe4e9e06f6dfdf66708b70aca3f781bed561f4f667b2d9c0d4559e36" 796 | dependencies = [ 797 | "version_check", 798 | ] 799 | 800 | [[package]] 801 | name = "smallvec" 802 | version = "1.6.1" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 805 | 806 | [[package]] 807 | name = "stdweb" 808 | version = "0.4.20" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 811 | dependencies = [ 812 | "discard", 813 | "rustc_version", 814 | "serde", 815 | "serde_json", 816 | "stdweb-derive", 817 | "stdweb-internal-macros", 818 | "stdweb-internal-runtime", 819 | "wasm-bindgen", 820 | ] 821 | 822 | [[package]] 823 | name = "stdweb-derive" 824 | version = "0.5.3" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 827 | dependencies = [ 828 | "proc-macro2", 829 | "quote", 830 | "serde", 831 | "serde_derive", 832 | "syn", 833 | ] 834 | 835 | [[package]] 836 | name = "stdweb-internal-macros" 837 | version = "0.2.9" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 840 | dependencies = [ 841 | "base-x", 842 | "proc-macro2", 843 | "quote", 844 | "serde", 845 | "serde_derive", 846 | "serde_json", 847 | "sha1", 848 | "syn", 849 | ] 850 | 851 | [[package]] 852 | name = "stdweb-internal-runtime" 853 | version = "0.1.5" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 856 | 857 | [[package]] 858 | name = "syn" 859 | version = "1.0.13" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" 862 | dependencies = [ 863 | "proc-macro2", 864 | "quote", 865 | "unicode-xid", 866 | ] 867 | 868 | [[package]] 869 | name = "tiff" 870 | version = "0.6.1" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" 873 | dependencies = [ 874 | "jpeg-decoder", 875 | "miniz_oxide 0.4.4", 876 | "weezl", 877 | ] 878 | 879 | [[package]] 880 | name = "time" 881 | version = "0.1.42" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" 884 | dependencies = [ 885 | "libc", 886 | "redox_syscall", 887 | "winapi", 888 | ] 889 | 890 | [[package]] 891 | name = "typenum" 892 | version = "1.13.0" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 895 | 896 | [[package]] 897 | name = "unicode-xid" 898 | version = "0.2.0" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 901 | 902 | [[package]] 903 | name = "version-compare" 904 | version = "0.0.10" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1" 907 | 908 | [[package]] 909 | name = "version_check" 910 | version = "0.9.3" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 913 | 914 | [[package]] 915 | name = "wasm-bindgen" 916 | version = "0.2.58" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" 919 | dependencies = [ 920 | "cfg-if 0.1.10", 921 | "wasm-bindgen-macro", 922 | ] 923 | 924 | [[package]] 925 | name = "wasm-bindgen-backend" 926 | version = "0.2.58" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" 929 | dependencies = [ 930 | "bumpalo", 931 | "lazy_static", 932 | "log", 933 | "proc-macro2", 934 | "quote", 935 | "syn", 936 | "wasm-bindgen-shared", 937 | ] 938 | 939 | [[package]] 940 | name = "wasm-bindgen-macro" 941 | version = "0.2.58" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" 944 | dependencies = [ 945 | "quote", 946 | "wasm-bindgen-macro-support", 947 | ] 948 | 949 | [[package]] 950 | name = "wasm-bindgen-macro-support" 951 | version = "0.2.58" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" 954 | dependencies = [ 955 | "proc-macro2", 956 | "quote", 957 | "syn", 958 | "wasm-bindgen-backend", 959 | "wasm-bindgen-shared", 960 | ] 961 | 962 | [[package]] 963 | name = "wasm-bindgen-shared" 964 | version = "0.2.58" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" 967 | 968 | [[package]] 969 | name = "weezl" 970 | version = "0.1.5" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" 973 | 974 | [[package]] 975 | name = "winapi" 976 | version = "0.3.7" 977 | source = "registry+https://github.com/rust-lang/crates.io-index" 978 | checksum = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" 979 | dependencies = [ 980 | "winapi-i686-pc-windows-gnu", 981 | "winapi-x86_64-pc-windows-gnu", 982 | ] 983 | 984 | [[package]] 985 | name = "winapi-i686-pc-windows-gnu" 986 | version = "0.4.0" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 989 | 990 | [[package]] 991 | name = "winapi-x86_64-pc-windows-gnu" 992 | version = "0.4.0" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 995 | -------------------------------------------------------------------------------- /mod_input/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_input" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | dynamic_lib = [] 11 | 12 | [lib] 13 | name = "mod_input" 14 | crate-type=["dylib"] 15 | 16 | [dependencies] 17 | 18 | [dependencies.game_state] 19 | path = "../game_state" 20 | -------------------------------------------------------------------------------- /mod_input/README.md: -------------------------------------------------------------------------------- 1 | # `mod_input` 2 | Extract any input events from Renderers, and make available for other subsystems -------------------------------------------------------------------------------- /mod_input/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use game_state::sdl2::video::Window; 4 | use game_state::state::{InputAccess, State, VariableAccess, WindowAccess, WorldAccess}; 5 | use game_state::thing::{CameraFacet, Direction}; 6 | 7 | use game_state::sdl2::{ 8 | event::Event as SdlEvent, keyboard::Keycode, mouse::MouseUtil, video::FullscreenType, 9 | }; 10 | 11 | // this module's purpose is to turn input events into meaningful application input 12 | // this might include closing windows, keyboard presses, mouse drags 13 | // mapping user settings to keyboard and mouse bindings 14 | 15 | // 16 | // TODO: 17 | // 1. simultaneous keypresses 18 | // 2. FPS camera rotation, clamp camera angles 19 | // 20 | fn grab_cursor(grab: bool, mouse: &MouseUtil) { 21 | mouse.show_cursor(!grab); 22 | mouse.set_relative_mouse_mode(grab); 23 | } 24 | 25 | #[no_mangle] 26 | pub extern "C" fn mod_input_load(state: &mut State) { 27 | state.on_input_load(); 28 | 29 | let mouse = state.sdl_context.mouse(); 30 | let mouse_grabbed = state.get_bool("mouse_grabbed").unwrap_or(true); 31 | grab_cursor(mouse_grabbed, &mouse); 32 | } 33 | 34 | #[no_mangle] 35 | pub extern "C" fn mod_input_update(state: &mut State, dt: &Duration) { 36 | let frame_events = state 37 | .sdl_subsystems 38 | .event_pump 39 | .poll_iter() 40 | .collect::>(); 41 | 42 | // TODO: wrap unsafe call in State, particularly WindowAccess 43 | let (sdlwin, _) = state.get_windows()[0].clone(); 44 | let mut window = unsafe { Window::from_ref(sdlwin) }; 45 | // 46 | 47 | let mut paused = state.get_bool("paused").unwrap_or(false); 48 | let mouse = state.sdl_context.mouse(); 49 | let mut mouse_grabbed = state.get_bool("mouse_grabbed").unwrap_or(true); 50 | let mut camera = &mut state.get_world().get_facets().cameras[0]; 51 | 52 | for event in frame_events { 53 | match event { 54 | SdlEvent::Quit { .. } => { 55 | println!("quitting..."); 56 | std::process::exit(0); 57 | } 58 | SdlEvent::KeyDown { 59 | keycode: Some(code), 60 | .. 61 | } => match code { 62 | Keycode::Escape => { 63 | if paused { 64 | println!("user pressed 'Esc' : unpaused."); 65 | paused = false; 66 | 67 | // re-grab the cursor if we are unpausing and it was grabbed 68 | if mouse_grabbed { 69 | grab_cursor(true, &mouse); 70 | } 71 | } else { 72 | println!("user pressed 'Esc' : paused."); 73 | camera.movement_dir = None; 74 | paused = true; 75 | 76 | // un-grab the cursor if we are paused 77 | if mouse_grabbed { 78 | grab_cursor(false, &mouse); 79 | } 80 | } 81 | } 82 | 83 | Keycode::Q => { 84 | if paused { 85 | println!("user pressed 'q' while paused : hard exit."); 86 | std::process::exit(0); 87 | } 88 | } 89 | 90 | // 91 | // TODO: pausing should prevent changes to the world, rather than guard input 92 | // 93 | Keycode::E if !paused => camera.movement_dir = Some(Direction::Up), 94 | Keycode::C if !paused => camera.movement_dir = Some(Direction::Down), 95 | Keycode::W if !paused => camera.movement_dir = Some(Direction::Forward), 96 | Keycode::A if !paused => camera.movement_dir = Some(Direction::Left), 97 | Keycode::S if !paused => camera.movement_dir = Some(Direction::Backward), 98 | Keycode::D if !paused => camera.movement_dir = Some(Direction::Right), 99 | Keycode::G if !paused => { 100 | mouse_grabbed = !mouse_grabbed; 101 | grab_cursor(mouse_grabbed, &mouse); 102 | } 103 | Keycode::F => match window.fullscreen_state() { 104 | FullscreenType::Off => window 105 | .set_fullscreen(FullscreenType::Desktop) 106 | .expect("unable to set fs"), 107 | _ => window 108 | .set_fullscreen(FullscreenType::Off) 109 | .expect("unable to set fs"), 110 | }, 111 | 112 | Keycode::Num9 => { 113 | println!("{}", camera.perspective.fovy()); 114 | } 115 | Keycode::Num0 => camera.perspective.set_fovy(camera.perspective.fovy() - 1.0), 116 | 117 | _ => {} 118 | }, 119 | SdlEvent::KeyUp { 120 | keycode: Some(code), 121 | .. 122 | } => { 123 | match code { 124 | // TODO: support multiple keypresses 125 | Keycode::E | Keycode::C | Keycode::W | Keycode::A | Keycode::S | Keycode::D => { 126 | camera.movement_dir = None; 127 | } 128 | _ => {} 129 | } 130 | } 131 | SdlEvent::MouseMotion { xrel, yrel, .. } => { 132 | if !paused { 133 | // println!( "mod_input: pos {:?} pitch {}, yaw {}", camera.pos, camera.pitch, camera.yaw); 134 | let sensitivity = 100.0; 135 | let (dx, dy) = (xrel as f32, yrel as f32); 136 | let xa = dx / sensitivity; 137 | let ya = dy / sensitivity; 138 | 139 | #[inline(always)] 140 | fn _rotate_camera(camera: &mut CameraFacet, xa: f32, ya: f32) { 141 | const TWO_PI: f32 = 2.0 * std::f32::consts::PI; 142 | const HALF_PI: f32 = 0.5 * std::f32::consts::PI; 143 | 144 | camera.yaw += xa; 145 | 146 | // round-robin yaw motion 147 | if camera.yaw.abs() > TWO_PI { 148 | camera.yaw = 0.0; 149 | } 150 | 151 | camera.pitch += -ya; 152 | // Clamp up/down rotation of the camera 153 | pub fn clamp(val: f32, min: f32, max: f32) -> f32 { 154 | assert!(min <= max); 155 | let mut x = val; 156 | if x < min { 157 | x = min; 158 | } 159 | if x > max { 160 | x = max; 161 | } 162 | x 163 | } 164 | camera.pitch = clamp(camera.pitch, -HALF_PI, HALF_PI); 165 | } 166 | 167 | _rotate_camera(camera, xa, ya); 168 | } 169 | } 170 | _ => {} 171 | } 172 | } 173 | camera.update(dt); 174 | state.set_bool("paused", paused); 175 | state.set_bool("mouse_grabbed", mouse_grabbed); 176 | } 177 | 178 | #[no_mangle] 179 | pub extern "C" fn mod_input_unload(state: &mut State) { 180 | state.on_input_unload(); 181 | } 182 | -------------------------------------------------------------------------------- /mod_rendering_opengl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_rendering_opengl" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | dynamic_lib = [] 11 | 12 | [lib] 13 | name = "mod_rendering_opengl" 14 | crate-type=["dylib"] 15 | 16 | [dependencies] 17 | glutin = "0.17" 18 | gl = "0.10" 19 | image = "0.17" #0.18 seems to fail to compile now... 20 | 21 | [dependencies.game_state] 22 | path = "../game_state" 23 | 24 | [build-dependencies] 25 | -------------------------------------------------------------------------------- /mod_rendering_opengl/README.md: -------------------------------------------------------------------------------- 1 | # `mod_rendering_opengl` 2 | 3 | this module is responsible for creating opengl renderers, and adding them to the global GameState 4 | -------------------------------------------------------------------------------- /mod_rendering_opengl/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use game_state::winit::EventsLoop; 4 | 5 | use std::sync::{Arc, Mutex}; 6 | 7 | mod renderer; 8 | 9 | use game_state::state::{DrawMode, RenderAccess, State, WindowAccess}; 10 | 11 | use renderer::opengl::OpenGLRenderer; 12 | 13 | #[no_mangle] 14 | pub extern "C" fn mod_rendering_opengl_load(state: &mut State) { 15 | let events_loop = Arc::new(Mutex::new(Some(EventsLoop::new()))); 16 | let windows = state 17 | .get_window_builders() 18 | .iter() 19 | .map(|x| x.clone()) 20 | .collect::>(); 21 | 22 | for w in windows { 23 | state.add_renderer(Box::new(OpenGLRenderer::new(w, events_loop.clone()))); 24 | } 25 | 26 | state.on_render_load(); 27 | } 28 | 29 | #[no_mangle] 30 | pub extern "C" fn mod_rendering_opengl_update(state: &mut State, dt: &Duration) { 31 | // queue each existing render layers for rendering 32 | state.push_render_layers(); 33 | state.present_all(); 34 | } 35 | 36 | #[no_mangle] 37 | pub extern "C" fn mod_rendering_opengl_unload(state: &mut State) { 38 | state.on_render_unload(); 39 | } 40 | -------------------------------------------------------------------------------- /mod_rendering_opengl/src/renderer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod opengl; 2 | -------------------------------------------------------------------------------- /mod_rendering_opengl/src/renderer/opengl/mod.rs: -------------------------------------------------------------------------------- 1 | use gl; 2 | use gl::types::*; 3 | 4 | use glutin; 5 | use glutin::GlContext; 6 | 7 | use game_state; 8 | use game_state::state::SceneGraph; 9 | use game_state::winit; 10 | use game_state::Renderer; 11 | 12 | use game_state::input; 13 | 14 | use std::sync::{Arc, Mutex}; 15 | 16 | use game_state::thing::CameraFacet; 17 | use game_state::Identity; 18 | 19 | use std::collections::VecDeque; 20 | 21 | pub struct OpenGLRenderer { 22 | id: Identity, 23 | gl_window: glutin::GlWindow, 24 | el: glutin::EventsLoop, 25 | render_layer_queue: VecDeque>, 26 | } 27 | impl OpenGLRenderer { 28 | pub fn new( 29 | window: winit::WindowBuilder, 30 | events_loop: Arc>>>, 31 | ) -> Self { 32 | let context = glutin::ContextBuilder::new(); 33 | let el = glutin::EventsLoop::new(); 34 | 35 | let gl_window = glutin::GlWindow::new(window.clone(), context, &el).unwrap(); 36 | 37 | unsafe { 38 | gl_window.make_current().unwrap(); 39 | } 40 | 41 | unsafe { 42 | gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _); 43 | gl::ClearColor(0.0, 0.1, 0.0, 1.0); 44 | } 45 | 46 | OpenGLRenderer { 47 | id: game_state::create_next_identity(), 48 | gl_window: gl_window, 49 | el, 50 | render_layer_queue: VecDeque::new(), 51 | } 52 | } 53 | 54 | fn render(&mut self, camera: &CameraFacet) { 55 | unsafe { 56 | gl::Clear(gl::COLOR_BUFFER_BIT); 57 | } 58 | 59 | loop { 60 | match self.render_layer_queue.pop_front() { 61 | Some(layer) => { 62 | 63 | //TODO : gather needed resources from the layer and render 64 | 65 | } 66 | None => break, 67 | } 68 | } 69 | 70 | self.gl_window 71 | .swap_buffers() 72 | .expect("failed to swap buffers"); 73 | } 74 | } 75 | 76 | impl game_state::Identifyable for OpenGLRenderer { 77 | fn identify(&self) -> Identity { 78 | self.id 79 | } 80 | } 81 | 82 | impl game_state::input::InputSource for OpenGLRenderer { 83 | fn get_input_events(&mut self) -> VecDeque { 84 | VecDeque::new() 85 | } 86 | } 87 | 88 | impl Renderer for OpenGLRenderer { 89 | fn load(&mut self) {} 90 | 91 | fn unload(&mut self) {} 92 | 93 | fn queue_render_layer(&mut self, layer: Arc) { 94 | self.render_layer_queue.push_back(layer); 95 | } 96 | 97 | fn present(&mut self, camera: &CameraFacet) { 98 | self.render(camera); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | name = "mod_rendering_vulkano" 4 | version = "0.1.0" 5 | authors = ["Daniel Werner "] 6 | edition = "2018" 7 | 8 | [features] 9 | default = [] 10 | 11 | # TODO: support static compilation and linking for final build. 12 | dynamic_lib = [] 13 | 14 | [lib] 15 | name = "mod_rendering_vulkano" 16 | crate-type=["dylib"] 17 | 18 | [dependencies] 19 | eyre = "0.6.5" 20 | image = "0.23" 21 | thiserror = "1.0" 22 | vulkano = "0.23" 23 | vulkano-shaders = "0.23" 24 | 25 | [dependencies.game_state] 26 | path = "../game_state" 27 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/README.md: -------------------------------------------------------------------------------- 1 | # `mod_rendering` 2 | 3 | this module is responsible for creating renderers, and adding them to the global GameState 4 | 5 | TODO: split this module into separate mods 6 | - mod_vulkan_renderer 7 | - mod_opengl_renderer 8 | - mod_software_renderer 9 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | } 3 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use game_state::sdl2::video::Window; 4 | use game_state::state::ModelAccess; 5 | use game_state::state::{RenderAccess, State, WindowAccess}; 6 | 7 | mod renderer; 8 | use renderer::vulkano::VulkanoRenderer; 9 | 10 | #[no_mangle] 11 | pub extern "C" fn mod_rendering_vulkano_load(state: &mut State) { 12 | let windows = state.get_windows(); 13 | 14 | for (w, draw_mode) in windows { 15 | // hack for sdl to own this "window", but pass it's surface to the underlying swapchain 16 | let win_ptr = { 17 | let sdlwin = unsafe { Window::from_ref(w) }; 18 | let c = unsafe { &*sdlwin.raw() }; 19 | crate::renderer::vulkano::vulkano_sdl2::WinPtr { raw: c as *const _ } 20 | }; 21 | let maybe_renderer = VulkanoRenderer::new(win_ptr, draw_mode, state.get_models()); 22 | 23 | match maybe_renderer { 24 | Ok(mut renderer) => { 25 | for model in state.get_models().iter() { 26 | renderer 27 | .upload_model(model.clone()) 28 | .unwrap_or_else(|_| todo!()); 29 | } 30 | state.add_renderer(Box::new(renderer)); 31 | } 32 | Err(err) => println!("Failed to load renderer. {}", err), 33 | } 34 | } 35 | 36 | state.on_render_load(); 37 | } 38 | 39 | #[no_mangle] 40 | pub extern "C" fn mod_rendering_vulkano_update(state: &mut State, _dt: &Duration) { 41 | // queue each existing render layers for rendering 42 | state.push_render_layers(); 43 | state.present_all(); 44 | } 45 | 46 | #[no_mangle] 47 | pub extern "C" fn mod_rendering_vulkano_unload(state: &mut State) { 48 | state.on_render_unload(); 49 | } 50 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/src/renderer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod vulkano; 2 | 3 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/src/renderer/vulkano/vertex.rs: -------------------------------------------------------------------------------- 1 | use game_state::model::Vertex as GSVertex; 2 | 3 | #[derive(Default, Debug, Clone)] 4 | pub struct Vertex { 5 | position: [f32; 3], 6 | uv: [f32; 2], 7 | normal: [f32; 3], 8 | } 9 | 10 | impl Vertex { 11 | pub fn from_gs_vertex(g: GSVertex) -> Self { 12 | println!("vertex {:?}", g); 13 | Vertex { 14 | position: [g.position.0, g.position.1, g.position.2], 15 | uv: [g.uvw.0, g.uvw.1], 16 | normal: [g.normal.0, g.normal.1, g.normal.2], 17 | } 18 | } 19 | } 20 | 21 | // the reason for this copying is to put the data into a struct we can 22 | // impl_vertex! on, in this crate... 23 | vulkano::impl_vertex!(Vertex, position, normal, uv); 24 | -------------------------------------------------------------------------------- /mod_rendering_vulkano/src/renderer/vulkano/vulkano_sdl2.rs: -------------------------------------------------------------------------------- 1 | use game_state::sdl2_sys::SDL_Window; 2 | use game_state::sdl2_sys::SDL_bool::SDL_FALSE; 3 | use game_state::sdl2_sys::SDL_SYSWM_TYPE; 4 | use game_state::sdl2_sys::{SDL_GetError, SDL_GetWindowWMInfo, SDL_SysWMinfo}; 5 | use game_state::sdl2_sys::{SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL}; 6 | use std::mem; 7 | use std::os::raw::c_char; 8 | use std::sync::Arc; 9 | use std::{ffi::CString, ops::Deref}; 10 | use vulkano::instance::{Instance, InstanceExtensions}; 11 | use vulkano::swapchain::{Surface, SurfaceCreationError}; 12 | 13 | #[derive(Copy, Clone)] 14 | pub struct WinPtr { 15 | pub raw: *const SDL_Window, 16 | } 17 | 18 | unsafe impl Send for WinPtr {} 19 | unsafe impl Sync for WinPtr {} 20 | impl Deref for WinPtr { 21 | type Target = *const SDL_Window; 22 | 23 | fn deref(&self) -> &Self::Target { 24 | &self.raw 25 | } 26 | } 27 | unsafe impl vulkano::SafeDeref for WinPtr {} 28 | 29 | #[derive(thiserror::Error, Debug)] 30 | pub enum ErrorType { 31 | #[error("unknown")] 32 | Unknown, 33 | #[error("platform not supported")] 34 | PlatformNotSupported, 35 | #[error("out of memory")] 36 | OutOfMemory, 37 | #[error("missing extension {0}")] 38 | MissingExtension(String), 39 | #[error("generic error {0}")] 40 | Generic(String), 41 | } 42 | 43 | pub fn required_extensions(window: WinPtr) -> Result { 44 | let wm_info = get_wminfo(window.raw)?; 45 | let mut extensions = InstanceExtensions { 46 | khr_surface: true, 47 | ..InstanceExtensions::none() 48 | }; 49 | let ideal = InstanceExtensions { 50 | khr_surface: true, 51 | khr_xlib_surface: true, 52 | khr_xcb_surface: true, 53 | khr_wayland_surface: true, 54 | khr_android_surface: true, 55 | khr_win32_surface: true, 56 | mvk_ios_surface: true, 57 | mvk_macos_surface: true, 58 | ..InstanceExtensions::none() 59 | }; 60 | match wm_info.subsystem { 61 | SDL_SYSWM_TYPE::SDL_SYSWM_X11 => extensions.khr_xlib_surface = true, 62 | SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND => extensions.khr_wayland_surface = true, 63 | SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS => extensions.khr_win32_surface = true, 64 | SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID => extensions.khr_android_surface = true, 65 | _ => return Err(ErrorType::PlatformNotSupported), 66 | } 67 | match InstanceExtensions::supported_by_core() { 68 | Ok(supported) => Ok(supported.intersection(&ideal)), 69 | Err(_) => Ok(InstanceExtensions::none()), 70 | } 71 | } 72 | 73 | pub fn build_vk_surface( 74 | window: WinPtr, 75 | instance: Arc, 76 | ) -> Result>, ErrorType> { 77 | let wm_info = get_wminfo(window.raw)?; 78 | unsafe { sdl2_to_surface(&wm_info, instance, window) } 79 | } 80 | 81 | #[cfg(target_os = "android")] 82 | unsafe fn sdl2_to_surface( 83 | wm_info: &SDL_SysWMinfo, 84 | instance: Arc, 85 | win: *mut SDL_Window, 86 | ) -> Result>, ErrorType> { 87 | let window = wm_info.info.android.window; 88 | translate_vk_result(Surface::from_anativewindow(instance, window, win)) 89 | } 90 | 91 | #[cfg(all(unix, not(target_os = "android")))] 92 | unsafe fn sdl2_to_surface( 93 | wm_info: &SDL_SysWMinfo, 94 | instance: Arc, 95 | win: WinPtr, 96 | ) -> Result>, ErrorType> { 97 | if wm_info.subsystem == SDL_SYSWM_TYPE::SDL_SYSWM_X11 { 98 | let display = wm_info.info.x11.display; 99 | let window = wm_info.info.x11.window; 100 | translate_vk_result(Surface::from_xlib(instance, display, window, win.clone())) 101 | } else if wm_info.subsystem == SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND { 102 | let display = wm_info.info.wl.display; 103 | let surface = wm_info.info.wl.surface; 104 | translate_vk_result(Surface::from_wayland( 105 | instance, 106 | display, 107 | surface, 108 | win.clone(), 109 | )) 110 | } else { 111 | unreachable!(); 112 | } 113 | } 114 | 115 | #[cfg(target_os = "windows")] 116 | unsafe fn sdl2_to_surface( 117 | wm_info: &SDL_SysWMinfo, 118 | instance: Arc, 119 | ) -> Result>, ErrorType> { 120 | let hinstance = wm_info.info.win.hinstance; 121 | let hwnd = wm_info.info.win.window; 122 | translate_vk_result(Surface::from_hwnd(instance, hinstance, hwnd)) 123 | } 124 | 125 | fn translate_vk_result( 126 | obj: Result>, SurfaceCreationError>, 127 | ) -> Result>, ErrorType> { 128 | match obj { 129 | Ok(x) => Ok(x), 130 | Err(SurfaceCreationError::OomError(_)) => Err(ErrorType::OutOfMemory), 131 | Err(SurfaceCreationError::MissingExtension { name: x }) => { 132 | Err(ErrorType::MissingExtension(String::from(x))) 133 | } 134 | } 135 | } 136 | 137 | fn get_wminfo(window: *const SDL_Window) -> Result { 138 | let mut wm_info: SDL_SysWMinfo; 139 | unsafe { 140 | wm_info = mem::zeroed(); 141 | } 142 | wm_info.version.major = SDL_MAJOR_VERSION as u8; 143 | wm_info.version.minor = SDL_MINOR_VERSION as u8; 144 | wm_info.version.patch = SDL_PATCHLEVEL as u8; 145 | unsafe { 146 | let window = window as *mut _; 147 | if SDL_GetWindowWMInfo(window, &mut wm_info as *mut SDL_SysWMinfo) == SDL_FALSE { 148 | let error = CString::from_raw(SDL_GetError() as *mut c_char); 149 | match error.into_string() { 150 | Ok(x) => return Err(ErrorType::Generic(x)), 151 | Err(_) => return Err(ErrorType::Unknown), 152 | } 153 | } 154 | } 155 | Ok(wm_info) 156 | } 157 | -------------------------------------------------------------------------------- /mod_simulation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mod_simulation" 3 | version = "0.1.0" 4 | authors = ["Daniel Werner "] 5 | edition = "2018" 6 | 7 | [features] 8 | default = [] 9 | dynamic_lib = [] 10 | 11 | [lib] 12 | name = "mod_simulation" 13 | crate-type=["dylib"] 14 | 15 | [dependencies] 16 | 17 | [dependencies.game_state] 18 | path = "../game_state" 19 | -------------------------------------------------------------------------------- /mod_simulation/README.md: -------------------------------------------------------------------------------- 1 | # `mod_simulation` 2 | 3 | Intended to serve as the simulation itself of the game world. 4 | 5 | -------------------------------------------------------------------------------- /mod_simulation/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | println!("Don't forget about me! (build.rs)"); 3 | } 4 | -------------------------------------------------------------------------------- /mod_simulation/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use game_state::state; 4 | 5 | #[no_mangle] 6 | pub extern "C" fn mod_simulation_load(_s: &mut state::State) {} 7 | 8 | #[no_mangle] 9 | pub extern "C" fn mod_simulation_update(_s: &mut state::State, _dt: &Duration) { 10 | //println!("sim tick, probably need deltatime (since this mod was last ticked)"); 11 | } 12 | 13 | #[no_mangle] 14 | pub extern "C" fn mod_simulation_unload(_s: &mut state::State) {} 15 | -------------------------------------------------------------------------------- /profile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shortcut to recompile both game_state and mod_rendering, in case of working on rendering innards 3 | export RUST_BACKTRACE=full 4 | export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json 5 | 6 | set -e 7 | ./rebuild-mods && cargo build $1 && heaptrack target/debug/sg_engine 8 | 9 | -------------------------------------------------------------------------------- /rebuild-mods: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # shortcut to recompile both game_state and mod_rendering, in case of working on rendering innards 4 | # 5 | # TODO: add better error reporting to this script so that we know when a mod fails to build. 6 | # EVENBETTER: write a launcher 7 | # 8 | export RUST_BACKTRACE=full 9 | set -e 10 | 11 | pids=() 12 | modules=( 13 | rendering_vulkano 14 | input 15 | gamepad 16 | asset_loader 17 | simulation 18 | ) 19 | for module in "${modules[@]}" 20 | do 21 | echo $module 22 | bash b $module $1 & 23 | pids+="$! " 24 | done 25 | wait $pids 26 | -------------------------------------------------------------------------------- /run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shortcut to recompile both game_state and mod_rendering, in case of working on rendering innards 3 | export RUST_BACKTRACE=full 4 | export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json 5 | 6 | set -e 7 | ./rebuild-mods && cargo run $1 8 | 9 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod libloader; 2 | -------------------------------------------------------------------------------- /src/libloader/mod.rs: -------------------------------------------------------------------------------- 1 | use std::fs; 2 | use std::path::Path; 3 | use std::time::{Duration, Instant, UNIX_EPOCH}; 4 | 5 | use ansi_term::Color::{Cyan, Green, Yellow}; 6 | use eyre::WrapErr; 7 | use game_state::state; 8 | use libloading::{Library, Symbol}; 9 | 10 | /// 11 | /// TODO: 12 | /// Add async futures layer over this - allowing module calls to be composed 13 | /// together as futures. 14 | /// 15 | /// (*)- Perhaps load modules into an evmap for lock-free concurrency? 16 | /// 17 | /// TODO: support a dynamically *defined* and dynamically loaded lib 18 | /// --> Load module definitions at runtime, even watch a mod folder and load them based on a def 19 | /// 20 | /// Mods support: 21 | /// 22 | /// Mods need to be named mod_, and must be unique. 23 | /// Each mod defines a set of extern "C" functions that are called 24 | /// at specific lifecycle points. 25 | /// 26 | /// Usage: 27 | /// let a_mod = load_mod!(modnamehere); 28 | /// let mut s = State::new(); 29 | /// loop { 30 | /// a_mod.check_update(&mut s); 31 | /// a_mod.tick(&mut s); 32 | /// } 33 | /// 34 | 35 | /// 36 | /// Macro for loading platform-specific shared lib (dll/so) 37 | /// 38 | #[macro_export] 39 | macro_rules! load_mod { 40 | ( $s:expr ) => {{ 41 | #[cfg(debug_assertions)] 42 | fn build_profile() -> &'static str { 43 | "debug" 44 | } 45 | 46 | #[cfg(not(debug_assertions))] 47 | fn build_profile() -> &'static str { 48 | "release" 49 | } 50 | 51 | let name = stringify!($s); 52 | let path = if cfg!(windows) { 53 | format!("mod_{0}/target/{1}/mod_{0}.dll", name, build_profile()) 54 | } else { 55 | format!( 56 | "mod_{0}/target/{1}/deps/libmod_{0}.so", 57 | name, 58 | build_profile() 59 | ) 60 | }; 61 | LibLoader::new(&path, name) 62 | }}; 63 | } 64 | 65 | /// 66 | /// LibLoader - an instance represents the managed loading of a dynamic shared library 67 | /// (.dll or .so, potentially in the future a .dylib) 68 | /// 69 | /// We keep track of last-modified date of the file, and when it changes we 70 | /// copy the file, along with a version counter to a temporary directory to load it from. 71 | /// 72 | pub struct LibLoader { 73 | filename: String, // Source filename to watch 74 | lib: Option, 75 | modified: Duration, 76 | version: u64, // Keep track of how many times we've loaded, 77 | // as we use this in the filename for the temp copy 78 | mod_name: String, 79 | } 80 | 81 | impl LibLoader { 82 | /// 83 | /// Returns the defined name of the module 84 | /// 85 | pub fn get_name(&self) -> &str { 86 | &self.mod_name 87 | } 88 | 89 | /// 90 | /// Construct a new wrapper for a dynamically loaded mod 91 | /// 92 | pub fn new(filename: &str, mod_name: &str) -> Self { 93 | let modified = Duration::from_millis(0); 94 | LibLoader { 95 | filename: filename.to_string(), 96 | lib: None, 97 | version: 0, 98 | mod_name: mod_name.to_string(), 99 | modified, 100 | } 101 | } 102 | 103 | /// 104 | /// Check for an update of the lib on disk. 105 | /// If there has been a change: 106 | /// - copy it to the tmp directory 107 | /// - call "unload" lifecycle event on the current mod if there is one 108 | /// - load the new library 109 | /// - call "load" lifecycle event on the newly loaded library, passing &mut State 110 | /// 111 | pub fn check_update(&mut self, state: &mut state::State) { 112 | let source = Path::new(&self.filename); 113 | let file_stem = source.file_stem().unwrap().to_str().unwrap(); 114 | 115 | match fs::metadata(&source) { 116 | Ok(new_meta) => { 117 | let modified = new_meta 118 | .modified() 119 | .expect("Unable to retrieve last modified date."); 120 | 121 | let duration: Duration = modified 122 | .duration_since(UNIX_EPOCH) 123 | .expect("Unable to get time."); 124 | 125 | if self.lib.is_none() || self.modified != duration { 126 | self.modified = duration; 127 | let new_filename = format!("target/{}_{}.so", file_stem, self.version); 128 | 129 | match fs::copy(&source, Path::new(&new_filename)) { 130 | Ok(_) => { 131 | if self.lib.is_some() { 132 | self.unload(state); 133 | } 134 | unsafe { 135 | match Library::new(&new_filename) { 136 | Ok(lib) => { 137 | self.version += 1; 138 | self.lib = Some(lib); 139 | self.load(state); 140 | } 141 | Err(err) => println!( 142 | "Unable to open new library: {} - err: {}", 143 | new_filename, err 144 | ), 145 | } 146 | } 147 | } 148 | Err(err) => println!( 149 | "Error copying file, target: {} - err: {}", 150 | new_filename, err 151 | ), 152 | } 153 | } 154 | } 155 | Err(err) => { 156 | // reset our state to allow any new lib to be loaded if one appears 157 | if self.lib.is_some() { 158 | self.unload(state); 159 | } 160 | self.lib = None; 161 | self.modified = Duration::from_millis(0); 162 | println!("unable to stat file! {}", err); 163 | } 164 | } 165 | } 166 | 167 | /// 168 | /// update() 169 | /// 170 | /// Call to the mod to update the state with the "update" normative lifecycle event 171 | /// 172 | pub fn update(&self, state: &mut state::State, delta_time: &Duration) -> Duration { 173 | let method_name = format!("mod_{}_update", self.mod_name); 174 | // todo: 175 | let start_time = Instant::now(); 176 | self.call_update(&method_name, state, delta_time); 177 | start_time.elapsed() 178 | } 179 | 180 | /// 181 | /// load() 182 | /// 183 | /// Trigger the "load" lifecycle event 184 | /// 185 | fn load(&self, state: &mut state::State) { 186 | let method_name = format!("mod_{}_load", self.mod_name); 187 | self.message("Loaded"); 188 | self.call(&method_name, state); 189 | } 190 | 191 | /// 192 | /// unload() 193 | /// 194 | /// Trigger the unload lifecycle event 195 | /// 196 | fn unload(&self, state: &mut state::State) { 197 | let method_name = format!("mod_{}_unload", self.mod_name); 198 | self.message("Unloaded"); 199 | self.call(&method_name, state); 200 | } 201 | 202 | /// 203 | /// message() 204 | /// 205 | /// Print an ansi_term colored message to the terminal. 206 | /// (used to signal changes in mod versions) 207 | /// 208 | fn message(&self, message: &str) { 209 | let source = Path::new(&self.filename); 210 | let file_stem = source.file_stem().unwrap().to_str().unwrap(); 211 | println!( 212 | "{}{} {} (version {}, {}){}", 213 | Green.bold().paint("["), 214 | Green.bold().paint(message), 215 | Yellow.paint(file_stem), 216 | Cyan.paint(format!("{}", self.version)), 217 | Cyan.paint(format!("{:?}", source)), 218 | Green.bold().paint("]") 219 | ); 220 | } 221 | 222 | /// 223 | /// call_update() 224 | /// 225 | /// call a method in the module by name, passing &mut State and a delta_time duration 226 | /// 227 | fn call_update(&self, method_name: &str, state: &mut state::State, delta_time: &Duration) { 228 | match self.lib { 229 | Some(ref lib) => unsafe { 230 | let method = method_name.as_bytes(); 231 | 232 | let maybe_func: eyre::Result< 233 | Symbol, 234 | > = lib.get(method).wrap_err("couldn't get symbol"); 235 | 236 | match maybe_func { 237 | Ok(func) => func(state, delta_time), 238 | Err(_) => println!( 239 | "Unable to call function: {} - method does not exist in lib: {:?}", 240 | method_name, lib 241 | ), 242 | } 243 | }, 244 | None => println!("Cannot call method {} - lib not found", method_name), 245 | } 246 | } 247 | 248 | fn call(&self, method_name: &str, state: &mut state::State) { 249 | match self.lib { 250 | Some(ref lib) => unsafe { 251 | let method = method_name.as_bytes(); 252 | 253 | let maybe_func: eyre::Result> = 254 | lib.get(method).wrap_err("could not get method"); 255 | 256 | match maybe_func { 257 | Ok(func) => func(state), 258 | Err(e) => println!( 259 | "Unable to call function: {} - method does not exist in lib: {:?} - {:?}", 260 | method_name, lib, e 261 | ), 262 | } 263 | }, 264 | None => println!("Cannot call method {} - lib not found", method_name), 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate engine; 3 | use engine::libloader::LibLoader; 4 | 5 | use game_state::state::DrawMode; 6 | use game_state::state::State; 7 | use std::time::{Duration, Instant}; 8 | 9 | use std::thread; 10 | 11 | use game_state::state::WindowAccess; 12 | 13 | fn main() { 14 | let mut state = State::default(); 15 | 16 | // TODO mod_audio 17 | // TODO mod_gui 18 | // TODO mod_network 19 | 20 | state.add_window( 21 | 800, 22 | 600, 23 | "sg-shell 1 (vulkano) wireframe", 24 | 0, 25 | 720, 26 | DrawMode::Wireframe(3.0), 27 | ); 28 | state.add_window( 29 | 1280, 30 | 720, 31 | "sg-shell 1 (vulkano) textured", 32 | 0, 33 | 0, 34 | DrawMode::Textured, 35 | ); 36 | 37 | let mut mods = Vec::new(); 38 | mods.push(load_mod!(gamepad)); 39 | mods.push(load_mod!(asset_loader)); 40 | mods.push(load_mod!(simulation)); 41 | 42 | mods.push(load_mod!(rendering_vulkano)); 43 | mods.push(load_mod!(input)); 44 | 45 | for m in mods.iter_mut() { 46 | m.check_update(&mut state); 47 | } 48 | 49 | let mut frame = 0; 50 | let frame_budget = 16000u128; // for 60 fps 51 | let mut last_update = Instant::now(); 52 | 53 | loop { 54 | // TODO: gather delta time instead 55 | 56 | let mut total_time = 0; 57 | for m in mods.iter() { 58 | let start_update = Instant::now(); 59 | let duration = m.update(&mut state, &(start_update - last_update)); 60 | if frame % 300 == 0 { 61 | print!( 62 | "|> {}: {total_time:>6} μs ", 63 | name = m.get_name(), 64 | total_time = duration.as_micros() 65 | ); 66 | } 67 | total_time += duration.as_micros(); 68 | } 69 | last_update = Instant::now(); 70 | if frame % 300 == 0 { 71 | println!( 72 | "|>= total time: {total_time:>6} μs", 73 | total_time = total_time 74 | ); 75 | } 76 | if frame % 30 == 0 { 77 | for m in mods.iter_mut() { 78 | m.check_update(&mut state); 79 | } 80 | } 81 | frame += 1; 82 | 83 | let wait = if frame_budget >= total_time { 84 | (frame_budget - total_time) / 1000 85 | } else { 86 | 0 87 | }; 88 | 89 | if wait > 0 { 90 | thread::sleep(Duration::from_millis(wait as u64)); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /todo.markdown: -------------------------------------------------------------------------------- 1 | ## Notes and Ideas, Links 2 | 3 | https://www.youtube.com/watch?v=c1H92b_uLdU 4 | 5 | - physics 6 | - network 7 | - audio (supercollider?) 8 | - rendering (vulkan) 9 | 10 | ## TODO: 11 | 12 | - networking 13 | - concurrency model 14 | - simulation 15 | - sim replication 16 | - with futures 17 | 18 | 19 | ## TODOs and notes on networking 20 | 21 | ### Idea: arbitrary model support through observables (a framework for simulation state sync?) 22 | 23 | #### Synchronization model 24 | 25 | http://gafferongames.com/networked-physics/snapshot-compression/ 26 | 27 | https://github.com/rygorous/gaffer_net/blob/master/main.cpp 28 | 29 | Target bandwidth range vs Actual bandwidth use 30 | 31 | - separate sync mechanisms for separate properties 32 | - prioritization of sync for different properties 33 | - adaptive sync methodology 34 | - express changing values as rate of change for interp 35 | - trans Simuation migration of objects 36 | - support simulation-level persistence (binary file, and maybe redis?) 37 | - property bounding (limit range, define quantization) 38 | - custom property serialization traits (e.g. quaternion's 'smallest three') 39 | - delta compression - send only what has changed 40 | - arbitrary precision types (like varint) 41 | - desync handling 42 | 43 | ### Knobs: 44 | - snapshot send rate (per second) 45 | - packet size 46 | - interpolation between snapshots in buffer 47 | - size of snapshot buffer 48 | - extrapolation of velocities, linear and angular 49 | - protocol (tcp/udp) - udp send/ack_send 50 | - data compression (none, zlib, compress) 51 | --------------------------------------------------------------------------------