├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .gitlab-ci.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── examples ├── button │ ├── .main.rs.swo │ ├── .main.rs.swp │ └── main.rs ├── canvas_struct │ └── main.rs ├── count1 │ └── main.rs ├── curve1 │ ├── .main.rs.swp │ └── main.rs ├── gravity │ └── main.rs ├── image │ └── main.rs ├── key_event │ └── main.rs ├── key_event_glob │ └── main.rs ├── snake │ └── main.rs └── wave │ └── main.rs └── src ├── .math.rs.swp ├── .vector.rs.swp ├── canvas.rs ├── canvas_glob.rs ├── color.rs ├── compute.rs ├── elements.rs ├── fonts.rs ├── fonts ├── Apache License.txt ├── DejaVuSans.ttf ├── GreatVibes-Regular.otf ├── OpenSans-Bold.ttf ├── OpenSans-BoldItalic.ttf ├── OpenSans-ExtraBold.ttf ├── OpenSans-ExtraBoldItalic.ttf ├── OpenSans-Italic.ttf ├── OpenSans-Light.ttf ├── OpenSans-LightItalic.ttf ├── OpenSans-Regular.ttf ├── OpenSans-Semibold.ttf ├── OpenSans-SemiboldItalic.ttf ├── Roboto-Black.ttf ├── Roboto-BlackItalic.ttf ├── Roboto-Bold.ttf ├── Roboto-BoldItalic.ttf ├── Roboto-Italic.ttf ├── Roboto-Light.ttf ├── Roboto-LightItalic.ttf ├── Roboto-Medium.ttf ├── Roboto-MediumItalic.ttf ├── Roboto-Regular.ttf ├── Roboto-Thin.ttf ├── Roboto-ThinItalic.ttf ├── RobotoCondensed-Bold.ttf ├── RobotoCondensed-BoldItalic.ttf ├── RobotoCondensed-Italic.ttf ├── RobotoCondensed-Light.ttf ├── RobotoCondensed-LightItalic.ttf ├── RobotoCondensed-Regular.ttf ├── matches.txt ├── names.txt └── scrpt1.py ├── lib.rs ├── mapping.rs ├── math.rs ├── page.rs ├── setup.rs ├── shaders.rs ├── text.rs ├── vector.rs └── vertex.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Build 13 | run: cargo build --verbose 14 | - name: Run tests 15 | run: cargo test --verbose 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: 'rust:latest' 2 | 3 | stages: 4 | - test 5 | - doc 6 | - build 7 | 8 | variables: 9 | CARGO_HOME: $CI_PROJECT_DIR/cargo 10 | APT_CACHE_DIR: $CI_PROJECT_DIR/apt 11 | 12 | before_script: 13 | - apt-get update -yq 14 | - apt-get install --yes cmake 15 | #- apt install libvulkan1 mesa-vulkan-drivers vulkan-utils 16 | #- apt-get install -o dir::cache::archives="$APT_CACHE_DIR" -y {{ DEPENDENCIES }} 17 | 18 | test: 19 | stage: test 20 | script: 21 | - rustc --version 22 | - cargo --version 23 | #- cargo test 24 | - cargo build --release 25 | 26 | pages: 27 | stage: doc 28 | script: 29 | - cargo doc --no-deps 30 | - mv target/doc public 31 | - echo '' > public/index.html 32 | artifacts: 33 | paths: 34 | - public 35 | only: 36 | - master 37 | 38 | cache: 39 | paths: 40 | - apt/ 41 | - cargo/ 42 | - target/ 43 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "metropolis" 3 | version = "0.9.1" 4 | authors = ["guy "] 5 | edition = "2018" 6 | description = "A high level easy to use graphics renderer" 7 | repository = "http://github.com/GuyL99/metropolis" 8 | readme = "README.md" 9 | categories = ["games","graphics","gui"] 10 | keywords = ["cli", "api","gui","gamedev","graphics"] 11 | license = "MIT" 12 | documentation = "https://docs.rs/metropolis/0.9.1/metropolis" 13 | gitlab = { repository = "https://gitlab.com/GuyL99/graphics-renderer", branch = "master" } 14 | 15 | 16 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 17 | 18 | [dependencies] 19 | vulkano = "0.16.0" 20 | vulkano-shaders = "0.16.0" 21 | vulkano-win = "0.16.0" 22 | winit = "0.19.5" 23 | rusttype = { version = "0.7", features = ["gpu_cache"] } 24 | png = "0.15" 25 | 26 | [profile.dev] 27 | opt-level = 0 28 | 29 | [profile.release] 30 | opt-level = 3 31 | 32 | 33 | [lib] 34 | name = "metropolis" 35 | 36 | path = "src/lib.rs" 37 | 38 | doctest = true 39 | 40 | doc = true 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Guy Levinger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Metropolis 2 | ![crates.io](https://img.shields.io/crates/v/metropolis.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![doc.rs](https://docs.rs/metropolis/badge.svg?version=0.9.1) 3 | ## What is it and what is it for? 4 | 5 | Metropolis is an easy to use high level graphics renderer written in rust, utilizing [vulkano](https://crates.io/crates/vulkano) and [winit](https://crates.io/crates/winit), 6 | I still have some work to do on it and I am currently still developing it and would love community input. 7 | Later I hope to develop a game engine using it but first I'll finish the renderer. 8 | ## How to install it? 9 | 10 | ### you can use cargo(the preferable and much easier and safe way): 11 | ```console 12 | :~$ cargo install metropolis 13 | ``` 14 | ### then install the vulkan required dependencies: 15 | ### if you have linux debian/ubuntu: 16 | ```console 17 | :~$ apt install libvulkan1 mesa-vulkan-drivers vulkan-utils 18 | ``` 19 | ### if you have fedora: 20 | ```console 21 | # dnf install vulkan vulkan-info 22 | ``` 23 | ### if you have arch linux: 24 | ```console 25 | # pacman -S vulkan-radeon lib32-vulkan-radeon 26 | ``` 27 | ### if you have mac: 28 | ```console 29 | :~$ xcode-select --install 30 | :~$ brew install cmake 31 | ``` 32 | ### for windows just install ninja. 33 | 34 | ## Usage 35 | 36 | Add the following to your Cargo.toml: 37 | ```rust 38 | [dependencies] 39 | metropolis = "0.9.1" 40 | ``` 41 | First use import the crate: 42 | ```rust 43 | extern crate metro; 44 | use metropolis::*; 45 | use metropolis::color::*; 46 | //if you want some math functions use math as well 47 | use metropolis::math::*; 48 | ``` 49 | 50 | Then you use the funcion size that creates a canvas(I wwould suggest to save height and width as variables so you can use them later 51 | ```rust 52 | fn main(){ 53 | let height = 600; 54 | let width = 800; 55 | size(width,height); 56 | ``` 57 | Next comes the setup(here I declare the varibles I will be using insode the looped function): 58 | ```rust 59 | let mut spd = 0; 60 | let mut acc = 1; 61 | let mut posy = 0; 62 | background(grayscale(220)); 63 | ``` 64 | Next comes the draw function, this function gets looped over so what's in it should be decided accordingly 65 | ```rust 66 | let draw =move || { 67 | spd+=1; 68 | if posy+50< height{ 69 | posy+=spd; 70 | } 71 | fill(rgb(255,0.1.3)); 72 | ellipse(400,posy,200,100); 73 | }; 74 | ``` 75 | Finally use the show() function to run the whole thing: 76 | ```rust 77 | show(draw); 78 | } 79 | ``` 80 | If you noticed - this program displays gravity working on an ellipse 81 | 82 | ## release notes: 83 | ### a patch version to fix the text module laggines: 84 | now the text module functions ok and on par with the rest of the crates FPS, the text can be between size 1 and 128. 85 | ### former versions release notes: 86 | #### 0.8.1 87 | I finally fixed the image module and now it could be used to place a png image wherever you want in the page in the same size as it was(the resize is on you...) 88 | #### 0.8.0 89 | I improved the text fps by a bit, added a Vector struct that allowes for some linear algebra related calculations, added from trait,display trait, and debug trait to color.
changed image functions: now only takes png images, and displays the whole image, I still have problems with it that I'm fixing.
changed the curve to work with bezier by default(beacuse of problems with te catmull rom chain) 90 | #### 0.7.0 91 | added the possiblity to use keyboard events see the examples:key_event and key_event_glob. I added mouse position getters and mouse scroll delta getters. 92 | #### 0.6.0 93 | you can now use a public mutithreading safe canvas struct, the matching example is called canvas_struct 94 | #### 0.5.1 95 | fixed a bug that caused the text vertecies to not be cleared at he end of each iteration of the draw function 96 | #### 0.5.0 97 | some of the math functions were deprecated due to community feedback:sin,cos,tan,abs 98 | I added an image module that allows you to load an image and display it(see the example for more details) 99 | #### 0.4.1 100 | fixed the text module slowdown for the non-text using canvases 101 | added FPS unsafe static 102 | added WIDTH/HEIGHT unsafe statics 103 | #### 0.4.0 104 | 1 - added a text module - uses text() and textSize() 105 | 2 - added abs() and absf() functions to math 106 | #### 0.3.3 107 | 1 - changed map to recieve generic variable 108 | 2 - added quad and square functions 109 | #### 0.3.2 110 | ported to vulkano 0.16, fixed the problem with the unclosing window! 111 | #### 0.3.1: 112 | there is a bezier curve, 2 function - one for vertex(4 x's and y's) and one for a chain(should have amout of values of 4+3*i such as 4,7,10,13...) 113 | #### 0.3.0: 114 | 1 - there is a mapping function called map 115 | 2 - there is a factorial function called factorial 116 | 3 - there is a function called linspace that create evenly spaced floats between two numbers 117 | 4 - there are curves - using the catmull rom chain algorithm there is are functions to create a curves: curve, curveVertex, catmull_rom_chain 118 | 119 | ### If you want to checkout the crate further that you should take a look in the [examples](https://github.com/GuyL99/metropolis/tree/master/examples) folder. 120 | ## Currently being developed: 121 | 1)dynamic line width.
122 | 2)page elements and multicanvas module
123 | 3)making the static mut into a lazy_static(in development).
124 | 4)3D.
125 | 5)HTML type file parsing into elements.
126 | 6)anithyng else from community feedback!
127 | 128 | # License 129 | This crate is primarily distributed under the terms of the MIT license 130 | See [LICENSE-MIT](https://github.com/GuyL99/metropolis/blob/master/LICENSE) for details. 131 | -------------------------------------------------------------------------------- /examples/button/.main.rs.swo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/examples/button/.main.rs.swo -------------------------------------------------------------------------------- /examples/button/.main.rs.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/examples/button/.main.rs.swp -------------------------------------------------------------------------------- /examples/button/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::canvas::*; 2 | use metropolis::color::*; 3 | use metropolis::elements::*; 4 | use metropolis::fonts::*; 5 | fn main(){ 6 | let mut canv = Canvas::new(800,600); 7 | canv.background(Color::from(20)); 8 | let mut btn1 = button(610,410,"btn1");//.style(Styles::RoundEdges); 9 | let mut clicked = false; 10 | let mut hovered = false; 11 | let draw = move |mut canvas:Canvas|->Canvas{ 12 | canvas.font(Fonts::RobotoBlackItalic); 13 | canvas.text_color(rgb(255,0,0)); 14 | //canvas.font(Fonts::DejaVuSans); 15 | if btn1.onHover(&canvas){ 16 | if !clicked{ 17 | btn1.color(rgb(255,100,00)); 18 | }else{ 19 | hovered = true; 20 | btn1.color(rgba(255,0,100,127)); 21 | } 22 | }else{ 23 | if btn1.onClick(&canvas){ 24 | clicked = true; 25 | btn1.color(rgb(255,0,100)); 26 | }else if !clicked{ 27 | btn1.color(grayscale(255)); 28 | } 29 | } 30 | if btn1.get_color()==rgba(255,0,100,127)&&!hovered{ 31 | btn1.color(rgb(255,0,100)); 32 | } 33 | //println!("{}",btn1.get_color()); 34 | canvas.attach(btn1); 35 | //println!("{:?}",btn1.get_size()); 36 | hovered = false; 37 | //println!("{:?}",canvas.fps); 38 | canvas 39 | }; 40 | canv.show(draw); 41 | } 42 | -------------------------------------------------------------------------------- /examples/canvas_struct/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::vector::*; 3 | use metropolis::canvas::Canvas; 4 | fn main(){ 5 | let height = 600; 6 | let width = 800; 7 | //size(width, height); 8 | let mut canv:Canvas= Canvas::new(width,height); 9 | let mut vec1 = Vector{vec:vec![1,2,3,4,6,8,9,10]}; 10 | vec1+=1; 11 | println!("{:?}",vec1); 12 | canv.background(grayscale(100)); 13 | let draw = |mut canvas:Canvas|->Canvas { 14 | let curve_vec: Vec<[i64; 2]> = vec![ 15 | [0, 400], 16 | [30, 370], 17 | [50, 300], 18 | [75, 257], 19 | [80, 240], 20 | [150, 150], 21 | [250, 050], 22 | ]; 23 | canvas.bezierCurve(curve_vec); 24 | canvas 25 | }; 26 | //canv = draw(); 27 | canv.show(draw); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /examples/count1/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::*; 3 | fn main() { 4 | size(800,600); 5 | background(grayscale(100)); 6 | let mut count = 0; 7 | let mut frames = 0; 8 | let mut str_from_count = "0"; 9 | let mut state =1; 10 | textSize(45); 11 | let draw = move||{ 12 | unsafe{ 13 | println!("{}",FPS); 14 | } 15 | frames += 1; 16 | 17 | match count{ 18 | 0=>{str_from_count = "00";}, 19 | 1=>{str_from_count = "10";}, 20 | 2=>{str_from_count = "02";}, 21 | 3=>{str_from_count = "3";}, 22 | 4=>{str_from_count = "4";}, 23 | 5=>{str_from_count = "5";}, 24 | 6=>{str_from_count = "6";}, 25 | 7=>{str_from_count = "7";}, 26 | 8=>{str_from_count = "8";}, 27 | 9=>{str_from_count = "9";}, 28 | _=>{}, 29 | } 30 | text(300,300,str_from_count); 31 | if frames % 15 == 0{ 32 | count += state; 33 | } 34 | if count == 9||count==0 { 35 | state *= -1 36 | } 37 | }; 38 | show(draw); 39 | } 40 | -------------------------------------------------------------------------------- /examples/curve1/.main.rs.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/examples/curve1/.main.rs.swp -------------------------------------------------------------------------------- /examples/curve1/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::*; 3 | use metropolis::math::*; 4 | fn main() { 5 | let height = 600; 6 | let width = 800; 7 | size(width, height); 8 | background(grayscale(100)); 9 | strokeWeight(8); 10 | let draw = move || { 11 | /*let curve_vec: Vec<[i64; 2]> = vec![ 12 | [0, 400], 13 | [30, 370], 14 | [50, 300], 15 | [75, 257], 16 | [80, 240], 17 | [150, 150], 18 | [250, 050], 19 | ];*/ 20 | //let curve_vec:Vec<[i64;2]> = vec![[400,0],[370,4],[300,50],[257,75],[80,240],[150,150]]; 21 | //bezierCurve(curve_vec); 22 | //let arr1 = bezier_points(1,5,2,4,3,4,4,1); 23 | let arr1 = catmull_rom_chain(1,5,2,5,3,5,4,4); 24 | for pt in arr1.iter(){ 25 | println!("val for x {} is: {}",pt[0],pt[1]); 26 | } 27 | }; 28 | show(draw); 29 | } 30 | -------------------------------------------------------------------------------- /examples/gravity/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::*; 3 | fn main() { 4 | let height = 900; 5 | let width = 1200; 6 | size(width, height); 7 | let mut spd = 0; 8 | let mut posy = 0; 9 | background(grayscale(100)); 10 | let draw = move || { 11 | spd += 1; 12 | if posy + 50 < height { 13 | posy += spd; 14 | } 15 | unsafe{ 16 | println!("{}",FPS); 17 | } 18 | fill(rgb(255, 0, 100)); 19 | //fill(0,0,00); 20 | //circle(400,posy,50); 21 | ellipse(400, posy, 200, 100); 22 | //arc(500,500,100,180); 23 | //line(800,800,posy,posy); 24 | }; 25 | show(draw); 26 | } 27 | -------------------------------------------------------------------------------- /examples/image/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::canvas::*; 3 | fn main() { 4 | let mut canv = Canvas::new(800,600); 5 | //canv.background(grayscale(100)); 6 | let mut posy = 0; 7 | let mut cnt = 0; 8 | let mut r = 100; 9 | let mut g = 100; 10 | let mut b = 100; 11 | //let image = img("/home/guyl/Desktop/saitama.png"); 12 | let image = img("/home/guyl/Desktop/rust.png");//.dimensions(500,500); 13 | let draw = move |mut canvas:Canvas|->Canvas{ 14 | canvas.display(image.clone(),canvas.mouseX(),canvas.mouseY()); 15 | //canvas.textSize(128); 16 | //canvas.text(100,100,"ttsstttadsas"); 17 | //canvas.text(500,500,"tttttadsas"); 18 | /*println!("{}",Color::from((r,g,b))); 19 | canvas.background(rgb(r,g,b)); 20 | if cnt%50 == 0{ 21 | posy+=100; 22 | } 23 | cnt+=1; 24 | if r == 255{ 25 | r=0; 26 | g=0; 27 | b=0; 28 | } 29 | if g == 255{ 30 | r+=1; 31 | g=0; 32 | b=0; 33 | } 34 | if b == 255{ 35 | g+=1; 36 | b=0; 37 | } 38 | b+=1; 39 | canvas.fill(Color::from((0,0,0))); 40 | canvas.rect(0,0,20,20); 41 | canvas.fill(Color::from((100,160,200))); 42 | canvas.rect(30,30,20,20);*/ 43 | println!("{}",canvas.fps); 44 | canvas 45 | }; 46 | canv.show(draw); 47 | } 48 | -------------------------------------------------------------------------------- /examples/key_event/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::canvas::*; 2 | use metropolis::color::*; 3 | fn main(){ 4 | let mut canv = Canvas::new(800,600); 5 | canv.background(grayscale(100)); 6 | canv.textSize(45); 7 | let draw = |mut canvas:Canvas|->Canvas{ 8 | let mut str_from_count = "0"; 9 | match canvas.keyPressed(){ 10 | keyCode::Key0=>{str_from_count = "0";}, 11 | keyCode::Key1=>{str_from_count = "1";}, 12 | keyCode::Key2=>{str_from_count = "2";}, 13 | keyCode::Key3=>{str_from_count = "3";}, 14 | keyCode::Key4=>{str_from_count = "4";}, 15 | keyCode::Key5=>{str_from_count = "5";}, 16 | keyCode::Key6=>{str_from_count = "6";}, 17 | keyCode::Key7=>{str_from_count = "7";}, 18 | keyCode::Key8=>{str_from_count = "8";}, 19 | keyCode::Key9=>{str_from_count = "9";}, 20 | _=>{}, 21 | 22 | } 23 | canvas.lockKeyEvent(); 24 | //println!("{:?}",canvas.mouseX()); 25 | canvas.text(300,300,str_from_count); 26 | canvas 27 | }; 28 | canv.show(draw); 29 | } 30 | -------------------------------------------------------------------------------- /examples/key_event_glob/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::*; 3 | fn main() { 4 | size(800,600); 5 | background(grayscale(100)); 6 | textSize(45); 7 | let draw = move||{ 8 | let mut str_from_count = "0"; 9 | match keyPressed(){ 10 | keyCode::Key0=>{str_from_count = "0";}, 11 | keyCode::Key1=>{str_from_count = "1";}, 12 | keyCode::Key2=>{str_from_count = "2";}, 13 | keyCode::Key3=>{str_from_count = "3";}, 14 | keyCode::Key4=>{str_from_count = "4";}, 15 | keyCode::Key5=>{str_from_count = "5";}, 16 | keyCode::Key6=>{str_from_count = "6";}, 17 | keyCode::Key7=>{str_from_count = "7";}, 18 | keyCode::Key8=>{str_from_count = "8";}, 19 | keyCode::Key9=>{str_from_count = "9";}, 20 | _=>{}, 21 | } 22 | lockKeyEvent(); 23 | text(300,300,str_from_count); 24 | }; 25 | show(draw); 26 | } 27 | -------------------------------------------------------------------------------- /examples/snake/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::canvas::*; 2 | use metropolis::color::*; 3 | fn main(){ 4 | let mut canv = Canvas::new(800,600); 5 | canv.background(grayscale(100)); 6 | let mut posx = 0; 7 | let mut posy = 0; 8 | let draw = move |mut canvas:Canvas|->Canvas{ 9 | match canvas.keyPressed(){ 10 | keyCode::W=>{posy-=10;}, 11 | keyCode::A=>{posx-=10;}, 12 | keyCode::S=>{posy+=10;}, 13 | keyCode::D=>{posx+=10;}, 14 | _=>{}, 15 | } 16 | if canvas.mouseClick() == MouseButton::Left{ 17 | canvas.fill(rgb(255,0,100)); 18 | canvas.ellipse(200,200,100,150); 19 | } 20 | //println!("{:?}",canvas.mouseX()); 21 | println!("{:?}",canvas.fps); 22 | canvas.fill(rgb(0,255,100)); 23 | canvas.rect(posx,posy,20,20); 24 | canvas 25 | }; 26 | canv.show(draw); 27 | } 28 | -------------------------------------------------------------------------------- /examples/wave/main.rs: -------------------------------------------------------------------------------- 1 | use metropolis::color::*; 2 | use metropolis::math::*; 3 | use metropolis::*; 4 | fn main() { 5 | size(800,600); 6 | background(grayscale(100)); 7 | let mut count = 0; 8 | let draw = move || { 9 | for i in 0..80{ 10 | for j in 0..60{ 11 | fill(grayscale(255)); 12 | rect(i as u16*10u16,j as u16*10u16,10,10); 13 | } 14 | } 15 | count+=1; 16 | if count ==100{ 17 | count =0; 18 | } 19 | }; 20 | show(draw); 21 | } 22 | -------------------------------------------------------------------------------- /src/.math.rs.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/.math.rs.swp -------------------------------------------------------------------------------- /src/.vector.rs.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/.vector.rs.swp -------------------------------------------------------------------------------- /src/canvas_glob.rs: -------------------------------------------------------------------------------- 1 | use crate::setup::*; 2 | use crate::vertex::*; 3 | use crate::fonts::*; 4 | use std::sync::Arc; 5 | use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer}; 6 | use vulkano::command_buffer::{AutoCommandBufferBuilder,AutoCommandBuffer}; 7 | use vulkano::swapchain; 8 | use vulkano::swapchain::{AcquireError, SwapchainCreationError}; 9 | use vulkano::sync; 10 | use vulkano::sync::{FlushError, GpuFuture}; 11 | use winit::{ElementState,KeyboardInput,Event, WindowEvent,VirtualKeyCode,ModifiersState}; 12 | use winit::dpi::LogicalPosition; 13 | use winit::MouseScrollDelta; 14 | use crate::text::{DrawText, DrawTextTrait}; 15 | use crate::{FPS,HEIGHT,WIDTH}; 16 | use std::time::{Duration, Instant}; 17 | use vulkano::image::{ImmutableImage, Dimensions}; 18 | use vulkano::sampler::{Sampler, SamplerAddressMode, Filter, MipmapMode}; 19 | use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; 20 | use winit::MouseButton; 21 | use vulkano::format::Format; 22 | #[derive(Copy,Clone,PartialEq)] 23 | pub struct Key{ 24 | pub keycode:Option, 25 | pub moder:ModifiersState, 26 | pub keep_key: bool, 27 | } 28 | impl Key{ 29 | pub fn get_mod(self)->ModifiersState{ 30 | self.moder 31 | } 32 | } 33 | #[derive(Copy,Clone,PartialEq)] 34 | pub struct MouseScroll{ 35 | pub delta:(i64,i64), 36 | pub moder:ModifiersState, 37 | } 38 | impl MouseScroll{ 39 | pub fn delta_x(self)->i64{ 40 | self.delta.0 41 | } 42 | pub fn delta_y(self)->i64{ 43 | self.delta.1//.PixelDelta.y as i64 44 | } 45 | } 46 | #[derive(Copy,Clone,PartialEq)] 47 | pub struct Mouse{ 48 | pub btn:Option, 49 | pub moder:ModifiersState, 50 | } 51 | #[derive(Copy, Clone, PartialEq)] 52 | pub struct CanvasGlob { 53 | pub size: (u16, u16), 54 | pub stroke: bool, 55 | pub color: [f32; 4], 56 | pub stroke_weight: u8, 57 | pub fill: bool, 58 | pub fill_color: [f32; 4], 59 | pub background_color: [f32; 4], 60 | pub fps: f32, 61 | pub resizeable: bool, 62 | pub text_size: f32, 63 | pub key:Key, 64 | pub cursor_pos:(u16,u16), 65 | pub mouse:Mouse, 66 | pub mouse_scroll:MouseScroll, 67 | pub font:Fonts, 68 | } 69 | impl CanvasGlob{ 70 | pub fn show(&mut self, mut draw_fn:F) 71 | where F :FnMut()+ 'static, 72 | { 73 | let set; 74 | let mut previous_frame_end; 75 | let (mut env, mut events_loop) = init(self.size.0, self.size.1); 76 | unsafe{ 77 | draw_fn(); 78 | match &TEXTURE{ 79 | Some((vec1,dim1))=>{ 80 | let vec_tex = vec1.to_vec(); 81 | let dimensions = *dim1; 82 | let (texture, tex_future) = { 83 | ImmutableImage::from_iter( 84 | vec_tex.iter().cloned(), 85 | dimensions, 86 | Format::R8G8B8A8Srgb, 87 | env.queue.clone() 88 | ).unwrap() 89 | }; 90 | let sampler = Sampler::new(env.device.clone(), Filter::Linear, Filter::Linear, 91 | MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat, 92 | SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap(); 93 | set = Some(Arc::new(PersistentDescriptorSet::start(env.tex_pipeline.clone(),0) 94 | .add_sampled_image(texture.clone(), sampler.clone()).unwrap() 95 | .build().unwrap())); 96 | previous_frame_end = Box::new(tex_future) as Box; 97 | }, 98 | None =>{ 99 | set =None; 100 | previous_frame_end =Box::new(env.previous_frame_end.unwrap()); 101 | } 102 | } 103 | } 104 | let mut text = DrawText::new(env.device.clone(), env.queue.clone(), env.swapchain.clone(), &env.images,self.font); 105 | let mut counter1 = 0; 106 | let start = Instant::now(); 107 | let mut end; 108 | let mut recreate_swapchain = env.recreate_swapchain; 109 | 110 | loop { 111 | let mut done = false; 112 | previous_frame_end.cleanup_finished(); 113 | events_loop.poll_events(|ev| match ev { 114 | Event::WindowEvent { 115 | event: WindowEvent::CloseRequested, 116 | .. 117 | } => done = true, 118 | Event::WindowEvent { 119 | event: WindowEvent::Resized(_), 120 | .. 121 | } => recreate_swapchain = true, 122 | Event::WindowEvent{event,..}=> 123 | match event{ 124 | WindowEvent::KeyboardInput{ 125 | input:KeyboardInput{ 126 | state: ElementState::Pressed, 127 | virtual_keycode: Some(key), 128 | modifiers, 129 | .. 130 | }, 131 | .. 132 | } => { 133 | if key == VirtualKeyCode::W && modifiers.ctrl{ 134 | done = true; 135 | } 136 | self.key = Key{keycode:Some(key),moder:modifiers,keep_key:false}; 137 | }, 138 | WindowEvent::CursorMoved{ 139 | position:LogicalPosition{x:posx,y:posy}, 140 | .. 141 | }=>{self.cursor_pos = (posx as u16,posy as u16);}, 142 | WindowEvent::MouseInput{ 143 | state: ElementState::Pressed, 144 | button: button1, 145 | modifiers, 146 | .. 147 | } => { 148 | self.mouse = Mouse{btn:Some(button1),moder:modifiers}; 149 | }, 150 | WindowEvent::MouseWheel{ 151 | delta: MouseScrollDelta::PixelDelta(pos), 152 | modifiers, 153 | .. 154 | } => { 155 | self.mouse_scroll = MouseScroll{delta:(pos.x as i64,pos.y as i64),moder:modifiers}; 156 | }, 157 | _=>{}, 158 | } 159 | _ => (), 160 | }); 161 | if done { 162 | return; 163 | } 164 | unsafe { 165 | env.dynamic_state.line_width = Some(CANVAS.stroke_weight as f32); 166 | match &STROKE_VERTECIES { 167 | Some(vec1) => STROKE_VERTECIES = Some(vec1.to_vec()), 168 | None => { 169 | let vec2 = vec![]; 170 | STROKE_VERTECIES = Some(vec2); 171 | } 172 | }; 173 | match &FILL_VERTECIES { 174 | Some(vec1) => FILL_VERTECIES = Some(vec1.to_vec()), 175 | None => { 176 | let vec2 = vec![]; 177 | FILL_VERTECIES = Some(vec2); 178 | } 179 | }; 180 | let stroke_vertex_buffer = CpuAccessibleBuffer::from_iter( 181 | env.device.clone(), 182 | BufferUsage::all(), 183 | STROKE_VERTECIES.clone().unwrap().iter().cloned(), 184 | ) 185 | .unwrap(); 186 | let fill_vertex_buffer = CpuAccessibleBuffer::from_iter( 187 | env.device.clone(), 188 | BufferUsage::all(), 189 | FILL_VERTECIES.clone().unwrap().iter().cloned(), 190 | ) 191 | .unwrap(); 192 | let window = env.surface.window(); 193 | if recreate_swapchain { 194 | let dimensions = { 195 | let dimensions: (u32, u32) = window 196 | .get_inner_size() 197 | .unwrap() 198 | .to_physical(window.get_hidpi_factor()) 199 | .into(); 200 | [dimensions.0, dimensions.1] 201 | }; 202 | let (new_swapchain, new_images) = 203 | match env.swapchain.recreate_with_dimension(dimensions) { 204 | Ok(r) => r, 205 | Err(SwapchainCreationError::UnsupportedDimensions) => continue, 206 | Err(err) => panic!("{:?}", err), 207 | }; 208 | env.swapchain = new_swapchain; 209 | env.framebuffers = window_size_dependent_setup( 210 | &new_images, 211 | env.render_pass.clone(), 212 | &mut env.dynamic_state, 213 | ); 214 | text = DrawText::new(env.device.clone(), env.queue.clone(), env.swapchain.clone(), &new_images,self.font); 215 | recreate_swapchain = false; 216 | } 217 | let (image_num, acquire_future) = 218 | match swapchain::acquire_next_image(env.swapchain.clone(), None) { 219 | Ok(r) => r, 220 | Err(AcquireError::OutOfDate) => { 221 | recreate_swapchain = true; 222 | continue; 223 | } 224 | Err(err) => panic!("{:?}", err), 225 | }; 226 | let clear_values = vec![self.background_color.into()]; 227 | let command_buffer:AutoCommandBuffer; 228 | match &TEXT_VEC { 229 | Some(vec1) => {if vec1.len()>0{ 230 | for txt in vec1{ 231 | text.queue_text(txt.position[0],txt.position[0], CANVAS.text_size, txt.color,txt.text); 232 | } 233 | match set.clone(){ 234 | Some(set)=>{ 235 | command_buffer = AutoCommandBufferBuilder::primary_one_time_submit( 236 | env.device.clone(), 237 | env.queue.family(), 238 | ) 239 | .unwrap() 240 | .begin_render_pass(env.framebuffers[image_num].clone(), false, clear_values) 241 | .unwrap() 242 | .draw( 243 | env.tex_pipeline.clone(), 244 | &env.dynamic_state, 245 | vec![fill_vertex_buffer.clone()], 246 | set.clone(), 247 | (), 248 | ) 249 | .unwrap() 250 | .draw( 251 | env.stroke_pipeline.clone(), 252 | &env.dynamic_state, 253 | vec![stroke_vertex_buffer.clone()], 254 | (), 255 | (), 256 | ) 257 | .unwrap() 258 | .end_render_pass() 259 | .unwrap() 260 | .draw_text(&mut text, image_num) 261 | .build() 262 | .unwrap(); 263 | }, 264 | None=>{ 265 | command_buffer = AutoCommandBufferBuilder::primary_one_time_submit( 266 | env.device.clone(), 267 | env.queue.family(), 268 | ) 269 | .unwrap() 270 | .begin_render_pass(env.framebuffers[image_num].clone(), false, clear_values) 271 | .unwrap() 272 | .draw( 273 | env.fill_pipeline.clone(), 274 | &env.dynamic_state, 275 | vec![fill_vertex_buffer.clone()], 276 | (), 277 | (), 278 | ) 279 | .unwrap() 280 | .draw( 281 | env.stroke_pipeline.clone(), 282 | &env.dynamic_state, 283 | vec![stroke_vertex_buffer.clone()], 284 | (), 285 | (), 286 | ) 287 | .unwrap() 288 | .end_render_pass() 289 | .unwrap() 290 | .draw_text(&mut text, image_num) 291 | .build() 292 | .unwrap(); 293 | } 294 | } 295 | }else{ 296 | match set.clone(){ 297 | Some(set)=>{ 298 | command_buffer = AutoCommandBufferBuilder::primary_one_time_submit( 299 | env.device.clone(), 300 | env.queue.family(), 301 | ) 302 | .unwrap() 303 | .begin_render_pass(env.framebuffers[image_num].clone(), false, clear_values) 304 | .unwrap() 305 | .draw( 306 | env.tex_pipeline.clone(), 307 | &env.dynamic_state, 308 | vec![fill_vertex_buffer.clone()], 309 | set.clone(), 310 | (), 311 | ) 312 | .unwrap() 313 | .draw( 314 | env.stroke_pipeline.clone(), 315 | &env.dynamic_state, 316 | vec![stroke_vertex_buffer.clone()], 317 | (), 318 | (), 319 | ) 320 | .unwrap() 321 | .end_render_pass() 322 | .unwrap() 323 | .build() 324 | .unwrap(); 325 | }, 326 | 327 | None =>{ 328 | command_buffer = AutoCommandBufferBuilder::primary_one_time_submit( 329 | env.device.clone(), 330 | env.queue.family(), 331 | ) 332 | .unwrap() 333 | .begin_render_pass(env.framebuffers[image_num].clone(), false, clear_values) 334 | .unwrap() 335 | .draw( 336 | env.fill_pipeline.clone(), 337 | &env.dynamic_state, 338 | vec![fill_vertex_buffer.clone()], 339 | (), 340 | (), 341 | ) 342 | .unwrap() 343 | .draw( 344 | env.stroke_pipeline.clone(), 345 | &env.dynamic_state, 346 | vec![stroke_vertex_buffer.clone()], 347 | (), 348 | (), 349 | ) 350 | .unwrap() 351 | .end_render_pass() 352 | .unwrap() 353 | .build() 354 | .unwrap(); 355 | } 356 | } 357 | } 358 | }, 359 | None => { 360 | let vec2 = vec![]; 361 | TEXT_VEC = Some(vec2); 362 | command_buffer = AutoCommandBufferBuilder::primary_one_time_submit( 363 | env.device.clone(), 364 | env.queue.family(), 365 | ) 366 | .unwrap() 367 | .build() 368 | .unwrap(); 369 | } 370 | }; 371 | //let prev =/* env.*/ (&mut *previous_frame_end).take(); 372 | let future = previous_frame_end 373 | .join(acquire_future) 374 | .then_execute(env.queue.clone(), command_buffer) 375 | .unwrap() 376 | .then_swapchain_present(env.queue.clone(), env.swapchain.clone(), image_num) 377 | .then_signal_fence_and_flush(); 378 | match future { 379 | Ok(future) => { 380 | future.wait(None).unwrap(); 381 | previous_frame_end = Box::new(future) as Box<_>; 382 | } 383 | Err(FlushError::OutOfDate) => { 384 | recreate_swapchain = true; 385 | previous_frame_end = 386 | Box::new(sync::now(env.device.clone())) as Box<_>; 387 | } 388 | Err(e) => { 389 | println!("{:?}", e); 390 | previous_frame_end = 391 | Box::new(sync::now(env.device.clone())) as Box<_>; 392 | } 393 | } 394 | end = Instant::now(); 395 | if (end-start)>Duration::new(1,0){ 396 | CANVAS.fps = counter1 as f32/(end-start).as_secs() as f32; 397 | FPS = CANVAS.fps; 398 | } 399 | HEIGHT = CANVAS.size.1; 400 | WIDTH = CANVAS.size.0; 401 | } 402 | zero_out(); 403 | draw_fn(); 404 | if self.key.keep_key == false{ 405 | self.key.keycode = Some(VirtualKeyCode::Power); 406 | } 407 | self.mouse.btn = Some(MouseButton::Other(99)); 408 | counter1+=1; 409 | } 410 | //}); 411 | } 412 | } 413 | pub fn zero_out() { 414 | unsafe { 415 | match &STROKE_VERTECIES { 416 | None => {} 417 | Some(_vec1) => { 418 | let vec2 = vec![]; 419 | STROKE_VERTECIES = Some(vec2); 420 | } 421 | }; 422 | match &FILL_VERTECIES { 423 | None => {} 424 | Some(_vec1) => { 425 | let vec2 = vec![]; 426 | FILL_VERTECIES = Some(vec2); 427 | } 428 | }; 429 | match &TEXT_VEC { 430 | None => {} 431 | Some(_vec1) => { 432 | let vec2 = vec![]; 433 | TEXT_VEC = Some(vec2); 434 | } 435 | }; 436 | } 437 | } 438 | pub static mut CANVAS: CanvasGlob = CanvasGlob { 439 | size: (0, 0), 440 | stroke: true, 441 | color: [0.0, 0.0, 0.0, 1.0], 442 | stroke_weight: 8, 443 | fill: false, 444 | fill_color: [1.0, 1.0, 1.0, 1.0], 445 | background_color: [1.0, 1.0, 1.0, 1.0], 446 | fps: 30.0, 447 | resizeable: false, 448 | text_size: 18.0, 449 | key:Key{keycode:None,moder:ModifiersState{shift:false,ctrl:false,alt:false,logo:false},keep_key:false}, 450 | cursor_pos:(0,0), 451 | mouse:Mouse{btn:None,moder:ModifiersState{shift:false,ctrl:false,alt:false,logo:false},}, 452 | mouse_scroll:MouseScroll{delta:(0,0),moder:ModifiersState{shift:false,ctrl:false,alt:false,logo:false},}, 453 | font:Fonts::DejaVuSans, 454 | 455 | }; 456 | pub static mut FILL_VERTECIES: Option> = None; 457 | pub static mut STROKE_VERTECIES: Option> = None; 458 | pub static mut TEXT_VEC: Option> = None; 459 | pub static mut TEXTURE:Option<(Vec,Dimensions)> = None; 460 | -------------------------------------------------------------------------------- /src/color.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Add; 2 | use std::ops::Sub; 3 | use std::fmt; 4 | ///a struct used for the coloring in this create 5 | #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] 6 | pub struct Color { 7 | r: u8, 8 | g: u8, 9 | b: u8, 10 | a: u8, 11 | } 12 | impl Color { 13 | pub fn get_g(self) -> u8 { 14 | self.g 15 | } 16 | pub fn get_r(self) -> u8 { 17 | self.r 18 | } 19 | pub fn get_b(self) -> u8 { 20 | self.b 21 | } 22 | pub fn get_a(self) -> u8 { 23 | self.a 24 | } 25 | } 26 | ///retrun Color sruct from rgb values 27 | pub fn rgb(r: u8, g: u8, b: u8) -> Color { 28 | Color { r, g, b, a: 255 } 29 | } 30 | ///retrun Color sruct from rgba values 31 | pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Color { 32 | Color { r, g, b, a } 33 | } 34 | ///retrun Color sruct from grayscale values - need fixing 35 | pub fn grayscale(gr: u8) -> Color { 36 | Color { 37 | r: gr, 38 | g: gr, //(gr as f32 *0.59) as u8, 39 | b: gr, //(gr as f32 *0.11) as u8, 40 | a: 255, 41 | } 42 | } 43 | impl fmt::Display for Color{ 44 | fn fmt(&self,f: &mut fmt::Formatter<'_>)->fmt::Result{ 45 | write!(f, "({},{},{},{})", self.r, self.g,self.b,self.a) 46 | } 47 | } 48 | impl fmt::Debug for Color{ 49 | fn fmt(&self,f: &mut fmt::Formatter<'_>)->fmt::Result{ 50 | write!(f, "({},{},{},{})", self.r, self.g,self.b,self.a) 51 | } 52 | } 53 | impl From<(u8,u8,u8)> for Color{ 54 | fn from(vals:(u8,u8,u8))->Self{ 55 | Color{r:vals.0,g:vals.1,b:vals.2,a:255} 56 | } 57 | } 58 | impl From<(u8,u8,u8,u8)> for Color{ 59 | fn from(vals:(u8,u8,u8,u8))->Self{ 60 | Color{r:vals.0,g:vals.1,b:vals.2,a:vals.3} 61 | } 62 | } 63 | impl From for Color{ 64 | fn from(vals:u8)->Self{ 65 | Color{r:vals,g:vals,b:vals,a:255} 66 | } 67 | } 68 | impl Add for Color{ 69 | type Output = Self; 70 | fn add(self,adder:u8)->Self{ 71 | Color{r:self.get_r()+adder,g:self.get_g()+adder,b:self.get_b()+adder,a:self.get_a()} 72 | } 73 | } 74 | impl Sub for Color{ 75 | type Output = Self; 76 | fn sub(self,adder:u8)->Self{ 77 | let mut r:i16 = self.get_r() as i16 -adder as i16; 78 | let mut g:i16 = self.get_g() as i16 -adder as i16; 79 | let mut b:i16 = self.get_b() as i16 -adder as i16; 80 | if r<0{ 81 | r=0; 82 | } 83 | if g<0{ 84 | g=0; 85 | } 86 | if b<0{ 87 | b=0; 88 | } 89 | Color{r:r as u8,g: g as u8,b: b as u8,a:self.get_a()} 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/compute.rs: -------------------------------------------------------------------------------- 1 | use crate::shaders::*; 2 | use std::sync::Arc; 3 | use vulkano::buffer::BufferUsage; 4 | use vulkano::buffer::CpuAccessibleBuffer; 5 | use vulkano::command_buffer::AutoCommandBufferBuilder; 6 | use vulkano::descriptor::descriptor_set::PersistentDescriptorSet; 7 | use vulkano::device::Device; 8 | use vulkano::device::DeviceExtensions; 9 | use vulkano::device::Features; 10 | use vulkano::instance::Instance; 11 | use vulkano::instance::InstanceExtensions; 12 | use vulkano::instance::PhysicalDevice; 13 | use vulkano::pipeline::ComputePipeline; 14 | use vulkano::sync; 15 | use vulkano::sync::GpuFuture; 16 | #[allow(non_camel_case_types)] 17 | #[allow(dead_code)] 18 | pub enum ops { 19 | Sub, 20 | Add, 21 | Mult, 22 | Div, 23 | FloatAdd, 24 | FloatSub, 25 | FloatDiv, 26 | FloatMult, 27 | AddVecs, 28 | SubVecs, 29 | FloatAddVecs, 30 | FloatSubVecs, 31 | FloatDivVecs, 32 | FloatMultVecs, 33 | } 34 | pub fn compute_ops(arr1: [T; 100], scalar1: T, op: ops) -> [T; 100] 35 | where 36 | T: Copy + Clone + Sync + Send, 37 | { 38 | let instance = 39 | Instance::new(None, &InstanceExtensions::none(), None).expect("failed to create instance"); 40 | 41 | let physical = PhysicalDevice::enumerate(&instance) 42 | .next() 43 | .expect("no device available"); 44 | 45 | let queue_family = physical 46 | .queue_families() 47 | .find(|&q| q.supports_compute()) 48 | .expect("couldn't find a compute queue family"); 49 | let (device, mut queues) = { 50 | Device::new( 51 | physical, 52 | &Features::none(), 53 | &DeviceExtensions::none(), 54 | [(queue_family, 0.5)].iter().cloned(), 55 | ) 56 | .expect("failed to create device") 57 | }; 58 | let queue = queues.next().unwrap(); 59 | match op { 60 | ops::Sub => { 61 | let shader = 62 | cs_sub::Shader::load(device.clone()).expect("failed to create shader module"); 63 | let compute_pipeline = Arc::new( 64 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 65 | .expect("failed to create compute pipeline"), 66 | ); 67 | let data_buffer = 68 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 69 | .expect("failed to create buffer"); 70 | let data_buffer2 = 71 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 72 | .expect("failed to create buffer"); 73 | let set = Arc::new( 74 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 75 | .add_buffer(data_buffer.clone()) 76 | .unwrap() 77 | .add_buffer(data_buffer2.clone()) 78 | .unwrap() 79 | .build() 80 | .unwrap(), 81 | ); 82 | let command_buffer = 83 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 84 | .unwrap() 85 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 86 | .unwrap() 87 | .build() 88 | .unwrap(); 89 | let _future = sync::now(device.clone()) 90 | .then_execute(queue.clone(), command_buffer) 91 | .unwrap() 92 | .then_signal_fence_and_flush() 93 | .unwrap() 94 | .wait(None) 95 | .unwrap(); 96 | let arr2 = data_buffer.read().unwrap(); 97 | return *arr2; 98 | } 99 | ops::Add => { 100 | let shader = 101 | cs_add::Shader::load(device.clone()).expect("failed to create shader module"); 102 | let compute_pipeline = Arc::new( 103 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 104 | .expect("failed to create compute pipeline"), 105 | ); 106 | let data_buffer = 107 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 108 | .expect("failed to create buffer"); 109 | let data_buffer2 = 110 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 111 | .expect("failed to create buffer"); 112 | let set = Arc::new( 113 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 114 | .add_buffer(data_buffer.clone()) 115 | .unwrap() 116 | .add_buffer(data_buffer2.clone()) 117 | .unwrap() 118 | .build() 119 | .unwrap(), 120 | ); 121 | let command_buffer = 122 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 123 | .unwrap() 124 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 125 | .unwrap() 126 | .build() 127 | .unwrap(); 128 | let _future = sync::now(device.clone()) 129 | .then_execute(queue.clone(), command_buffer) 130 | .unwrap() 131 | .then_signal_fence_and_flush() 132 | .unwrap() 133 | .wait(None) 134 | .unwrap(); 135 | let arr2 = data_buffer.read().unwrap(); 136 | return *arr2; 137 | } 138 | ops::Div => { 139 | let shader = 140 | cs_div::Shader::load(device.clone()).expect("failed to create shader module"); 141 | let compute_pipeline = Arc::new( 142 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 143 | .expect("failed to create compute pipeline"), 144 | ); 145 | let data_buffer = 146 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 147 | .expect("failed to create buffer"); 148 | let data_buffer2 = 149 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 150 | .expect("failed to create buffer"); 151 | let set = Arc::new( 152 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 153 | .add_buffer(data_buffer.clone()) 154 | .unwrap() 155 | .add_buffer(data_buffer2.clone()) 156 | .unwrap() 157 | .build() 158 | .unwrap(), 159 | ); 160 | let command_buffer = 161 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 162 | .unwrap() 163 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 164 | .unwrap() 165 | .build() 166 | .unwrap(); 167 | let _future = sync::now(device.clone()) 168 | .then_execute(queue.clone(), command_buffer) 169 | .unwrap() 170 | .then_signal_fence_and_flush() 171 | .unwrap() 172 | .wait(None) 173 | .unwrap(); 174 | let arr2 = data_buffer.read().unwrap(); 175 | return *arr2; 176 | } 177 | ops::Mult => { 178 | let shader = 179 | cs_mult::Shader::load(device.clone()).expect("failed to create shader module"); 180 | let compute_pipeline = Arc::new( 181 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 182 | .expect("failed to create compute pipeline"), 183 | ); 184 | let data_buffer = 185 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 186 | .expect("failed to create buffer"); 187 | let data_buffer2 = 188 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 189 | .expect("failed to create buffer"); 190 | let set = Arc::new( 191 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 192 | .add_buffer(data_buffer.clone()) 193 | .unwrap() 194 | .add_buffer(data_buffer2.clone()) 195 | .unwrap() 196 | .build() 197 | .unwrap(), 198 | ); 199 | let command_buffer = 200 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 201 | .unwrap() 202 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 203 | .unwrap() 204 | .build() 205 | .unwrap(); 206 | let _future = sync::now(device.clone()) 207 | .then_execute(queue.clone(), command_buffer) 208 | .unwrap() 209 | .then_signal_fence_and_flush() 210 | .unwrap() 211 | .wait(None) 212 | .unwrap(); 213 | let arr2 = data_buffer.read().unwrap(); 214 | return *arr2; 215 | } 216 | ops::FloatAdd => { 217 | let shader = 218 | cs_float_add::Shader::load(device.clone()).expect("failed to create shader module"); 219 | let compute_pipeline = Arc::new( 220 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 221 | .expect("failed to create compute pipeline"), 222 | ); 223 | let data_buffer = 224 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 225 | .expect("failed to create buffer"); 226 | let data_buffer2 = 227 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 228 | .expect("failed to create buffer"); 229 | let set = Arc::new( 230 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 231 | .add_buffer(data_buffer.clone()) 232 | .unwrap() 233 | .add_buffer(data_buffer2.clone()) 234 | .unwrap() 235 | .build() 236 | .unwrap(), 237 | ); 238 | let command_buffer = 239 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 240 | .unwrap() 241 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 242 | .unwrap() 243 | .build() 244 | .unwrap(); 245 | let _future = sync::now(device.clone()) 246 | .then_execute(queue.clone(), command_buffer) 247 | .unwrap() 248 | .then_signal_fence_and_flush() 249 | .unwrap() 250 | .wait(None) 251 | .unwrap(); 252 | let arr2 = data_buffer.read().unwrap(); 253 | return *arr2; 254 | } 255 | ops::FloatSub => { 256 | let shader = 257 | cs_float_sub::Shader::load(device.clone()).expect("failed to create shader module"); 258 | let compute_pipeline = Arc::new( 259 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 260 | .expect("failed to create compute pipeline"), 261 | ); 262 | let data_buffer = 263 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 264 | .expect("failed to create buffer"); 265 | let data_buffer2 = 266 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 267 | .expect("failed to create buffer"); 268 | let set = Arc::new( 269 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 270 | .add_buffer(data_buffer.clone()) 271 | .unwrap() 272 | .add_buffer(data_buffer2.clone()) 273 | .unwrap() 274 | .build() 275 | .unwrap(), 276 | ); 277 | let command_buffer = 278 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 279 | .unwrap() 280 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 281 | .unwrap() 282 | .build() 283 | .unwrap(); 284 | let _future = sync::now(device.clone()) 285 | .then_execute(queue.clone(), command_buffer) 286 | .unwrap() 287 | .then_signal_fence_and_flush() 288 | .unwrap() 289 | .wait(None) 290 | .unwrap(); 291 | let arr2 = data_buffer.read().unwrap(); 292 | return *arr2; 293 | } 294 | ops::FloatDiv => { 295 | let shader = 296 | cs_float_div::Shader::load(device.clone()).expect("failed to create shader module"); 297 | let compute_pipeline = Arc::new( 298 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 299 | .expect("failed to create compute pipeline"), 300 | ); 301 | let data_buffer = 302 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 303 | .expect("failed to create buffer"); 304 | let data_buffer2 = 305 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 306 | .expect("failed to create buffer"); 307 | let set = Arc::new( 308 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 309 | .add_buffer(data_buffer.clone()) 310 | .unwrap() 311 | .add_buffer(data_buffer2.clone()) 312 | .unwrap() 313 | .build() 314 | .unwrap(), 315 | ); 316 | let command_buffer = 317 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 318 | .unwrap() 319 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 320 | .unwrap() 321 | .build() 322 | .unwrap(); 323 | let _future = sync::now(device.clone()) 324 | .then_execute(queue.clone(), command_buffer) 325 | .unwrap() 326 | .then_signal_fence_and_flush() 327 | .unwrap() 328 | .wait(None) 329 | .unwrap(); 330 | let arr2 = data_buffer.read().unwrap(); 331 | return *arr2; 332 | } 333 | ops::FloatMult => { 334 | let shader = cs_float_mult::Shader::load(device.clone()) 335 | .expect("failed to create shader module"); 336 | let compute_pipeline = Arc::new( 337 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 338 | .expect("failed to create compute pipeline"), 339 | ); 340 | let data_buffer = 341 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 342 | .expect("failed to create buffer"); 343 | let data_buffer2 = 344 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), scalar1) 345 | .expect("failed to create buffer"); 346 | let set = Arc::new( 347 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 348 | .add_buffer(data_buffer.clone()) 349 | .unwrap() 350 | .add_buffer(data_buffer2.clone()) 351 | .unwrap() 352 | .build() 353 | .unwrap(), 354 | ); 355 | let command_buffer = 356 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 357 | .unwrap() 358 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 359 | .unwrap() 360 | .build() 361 | .unwrap(); 362 | let _future = sync::now(device.clone()) 363 | .then_execute(queue.clone(), command_buffer) 364 | .unwrap() 365 | .then_signal_fence_and_flush() 366 | .unwrap() 367 | .wait(None) 368 | .unwrap(); 369 | let arr2 = data_buffer.read().unwrap(); 370 | return *arr2; 371 | } 372 | _ => { 373 | return arr1; 374 | } 375 | } 376 | } 377 | pub fn compute_ops2(arr1: [T; 100], arr2: [T; 100], op: ops) -> [T; 100] 378 | where 379 | T: Copy + Clone + Sync + Send, 380 | { 381 | let instance = 382 | Instance::new(None, &InstanceExtensions::none(), None).expect("failed to create instance"); 383 | 384 | let physical = PhysicalDevice::enumerate(&instance) 385 | .next() 386 | .expect("no device available"); 387 | 388 | let queue_family = physical 389 | .queue_families() 390 | .find(|&q| q.supports_compute()) 391 | .expect("couldn't find a compute queue family"); 392 | 393 | let (device, mut queues) = { 394 | Device::new( 395 | physical, 396 | &Features::none(), 397 | &DeviceExtensions::none(), 398 | [(queue_family, 0.5)].iter().cloned(), 399 | ) 400 | .expect("failed to create device") 401 | }; 402 | let queue = queues.next().unwrap(); 403 | match op { 404 | ops::FloatSubVecs => { 405 | let shader = cs_float_sub_vec::Shader::load(device.clone()) 406 | .expect("failed to create shader module"); 407 | let compute_pipeline = Arc::new( 408 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 409 | .expect("failed to create compute pipeline"), 410 | ); 411 | let data_buffer = 412 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 413 | .expect("failed to create buffer"); 414 | let data_buffer2 = 415 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr2) 416 | .expect("failed to create buffer"); 417 | let set = Arc::new( 418 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 419 | .add_buffer(data_buffer.clone()) 420 | .unwrap() 421 | .add_buffer(data_buffer2.clone()) 422 | .unwrap() 423 | .build() 424 | .unwrap(), 425 | ); 426 | let command_buffer = 427 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 428 | .unwrap() 429 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 430 | .unwrap() 431 | .build() 432 | .unwrap(); 433 | let _future = sync::now(device.clone()) 434 | .then_execute(queue.clone(), command_buffer) 435 | .unwrap() 436 | .then_signal_fence_and_flush() 437 | .unwrap() 438 | .wait(None) 439 | .unwrap(); 440 | let arr3 = data_buffer.read().unwrap(); 441 | return *arr3; 442 | } 443 | ops::AddVecs => { 444 | let shader = 445 | cs_add_vec::Shader::load(device.clone()).expect("failed to create shader module"); 446 | let compute_pipeline = Arc::new( 447 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 448 | .expect("failed to create compute pipeline"), 449 | ); 450 | let data_buffer = 451 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 452 | .expect("failed to create buffer"); 453 | let data_buffer2 = 454 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr2) 455 | .expect("failed to create buffer"); 456 | let set = Arc::new( 457 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 458 | .add_buffer(data_buffer.clone()) 459 | .unwrap() 460 | .add_buffer(data_buffer2.clone()) 461 | .unwrap() 462 | .build() 463 | .unwrap(), 464 | ); 465 | let command_buffer = 466 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 467 | .unwrap() 468 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 469 | .unwrap() 470 | .build() 471 | .unwrap(); 472 | let _future = sync::now(device.clone()) 473 | .then_execute(queue.clone(), command_buffer) 474 | .unwrap() 475 | .then_signal_fence_and_flush() 476 | .unwrap() 477 | .wait(None) 478 | .unwrap(); 479 | let arr3 = data_buffer.read().unwrap(); 480 | return *arr3; 481 | } 482 | ops::SubVecs => { 483 | let shader = 484 | cs_sub_vec::Shader::load(device.clone()).expect("failed to create shader module"); 485 | let compute_pipeline = Arc::new( 486 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 487 | .expect("failed to create compute pipeline"), 488 | ); 489 | let data_buffer = 490 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 491 | .expect("failed to create buffer"); 492 | let data_buffer2 = 493 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr2) 494 | .expect("failed to create buffer"); 495 | let set = Arc::new( 496 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 497 | .add_buffer(data_buffer.clone()) 498 | .unwrap() 499 | .add_buffer(data_buffer2.clone()) 500 | .unwrap() 501 | .build() 502 | .unwrap(), 503 | ); 504 | let command_buffer = 505 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 506 | .unwrap() 507 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 508 | .unwrap() 509 | .build() 510 | .unwrap(); 511 | let _future = sync::now(device.clone()) 512 | .then_execute(queue.clone(), command_buffer) 513 | .unwrap() 514 | .then_signal_fence_and_flush() 515 | .unwrap() 516 | .wait(None) 517 | .unwrap(); 518 | let arr3 = data_buffer.read().unwrap(); 519 | return *arr3; 520 | } 521 | ops::FloatDivVecs => { 522 | let shader = cs_float_div_vec::Shader::load(device.clone()) 523 | .expect("failed to create shader module"); 524 | let compute_pipeline = Arc::new( 525 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 526 | .expect("failed to create compute pipeline"), 527 | ); 528 | let data_buffer = 529 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 530 | .expect("failed to create buffer"); 531 | let data_buffer2 = 532 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr2) 533 | .expect("failed to create buffer"); 534 | let set = Arc::new( 535 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 536 | .add_buffer(data_buffer.clone()) 537 | .unwrap() 538 | .add_buffer(data_buffer2.clone()) 539 | .unwrap() 540 | .build() 541 | .unwrap(), 542 | ); 543 | let command_buffer = 544 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 545 | .unwrap() 546 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 547 | .unwrap() 548 | .build() 549 | .unwrap(); 550 | let _future = sync::now(device.clone()) 551 | .then_execute(queue.clone(), command_buffer) 552 | .unwrap() 553 | .then_signal_fence_and_flush() 554 | .unwrap() 555 | .wait(None) 556 | .unwrap(); 557 | let arr3 = data_buffer.read().unwrap(); 558 | return *arr3; 559 | } 560 | ops::FloatMultVecs => { 561 | let shader = cs_float_mult_vec::Shader::load(device.clone()) 562 | .expect("failed to create shader module"); 563 | let compute_pipeline = Arc::new( 564 | ComputePipeline::new(device.clone(), &shader.main_entry_point(), &()) 565 | .expect("failed to create compute pipeline"), 566 | ); 567 | let data_buffer = 568 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr1) 569 | .expect("failed to create buffer"); 570 | let data_buffer2 = 571 | CpuAccessibleBuffer::from_data(device.clone(), BufferUsage::all(), arr2) 572 | .expect("failed to create buffer"); 573 | let set = Arc::new( 574 | PersistentDescriptorSet::start(compute_pipeline.clone(), 0) 575 | .add_buffer(data_buffer.clone()) 576 | .unwrap() 577 | .add_buffer(data_buffer2.clone()) 578 | .unwrap() 579 | .build() 580 | .unwrap(), 581 | ); 582 | let command_buffer = 583 | AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()) 584 | .unwrap() 585 | .dispatch([100, 1, 1], compute_pipeline.clone(), set.clone(), ()) 586 | .unwrap() 587 | .build() 588 | .unwrap(); 589 | let _future = sync::now(device.clone()) 590 | .then_execute(queue.clone(), command_buffer) 591 | .unwrap() 592 | .then_signal_fence_and_flush() 593 | .unwrap() 594 | .wait(None) 595 | .unwrap(); 596 | let arr3 = data_buffer.read().unwrap(); 597 | return *arr3; 598 | } 599 | _ => { 600 | return arr1; 601 | } 602 | } 603 | } 604 | -------------------------------------------------------------------------------- /src/elements.rs: -------------------------------------------------------------------------------- 1 | use crate::color::*; 2 | use crate::canvas::*; 3 | pub trait PageElement { 4 | fn draw(self,canvas:&mut Canvas); 5 | #[allow(non_snake_case)] 6 | fn onClick(self,canvas:&Canvas)->bool; 7 | #[allow(non_snake_case)] 8 | fn onHover(self,canvas:&Canvas)->bool; 9 | } 10 | #[derive(Copy,Clone)] 11 | pub enum Styles{ 12 | Normal, 13 | RoundEdges, 14 | Triangular, 15 | Elliptic, 16 | } 17 | #[derive(Clone,Copy)] 18 | pub struct Button{ 19 | color:Color, 20 | x:u16, 21 | y:u16, 22 | width:u16, 23 | height:u16, 24 | border_width:u8, 25 | style:Styles, 26 | text:&'static str, 27 | } 28 | impl PageElement for Button { 29 | fn draw(self,canvas:&mut Canvas){ 30 | canvas.textSize(12); 31 | canvas.text(self.x+self.border_width as u16+6,self.y+self.border_width as u16+(self.height/2)+1,self.text); 32 | match self.style{ 33 | Styles::Normal=>{ 34 | /*canvas.fill(self.color-20); 35 | canvas.rect(self.x,self.y,self.width,self.height);*/ 36 | canvas.fill(self.color); 37 | canvas.rect(self.x+self.border_width as u16,self.y+self.border_width as u16,self.width-(self.border_width*2) as u16,self.height-(self.border_width*2) as u16); 38 | }, 39 | Styles::RoundEdges=>{ 40 | canvas.line(self.x+2,self.y,self.x+self.width-4,self.y); 41 | canvas.bezierCurveVertex((self.x+self.width-4) as i64,self.y as i64,(self.x+self.width-2) as i64,(self.y+2) as i64,(self.x+self.width-4) as i64,self.y as i64,(self.x+self.width-2) as i64,(self.y+2) as i64); 42 | canvas.line(self.x+self.width-2,self.y+2,self.x+self.width-2,self.y+self.height-4); 43 | canvas.bezierCurveVertex((self.x+self.width-2) as i64,(self.y+self.height-4) as i64,(self.x+self.width-4) as i64,(self.y+self.height-2) as i64,(self.x+self.width-2) as i64,(self.y+self.height-4) as i64,(self.x+self.width-4) as i64,(self.y+self.height-2) as i64); 44 | canvas.line(self.x+self.width-4,self.y+self.height-2,self.x+2,self.y+self.height-2); 45 | canvas.bezierCurveVertex((self.x+2) as i64,(self.y+self.height-2) as i64,(self.x) as i64,(self.y+self.height-4) as i64,(self.x+2) as i64,(self.y+self.height-2) as i64,(self.x) as i64,(self.y+self.height-4) as i64); 46 | canvas.line(self.x,self.y+self.height-4,self.x,self.y+2); 47 | canvas.bezierCurveVertex((self.x) as i64,(self.y+2) as i64,(self.x+2) as i64,self.y as i64,(self.x) as i64,(self.y+2) as i64,(self.x+2) as i64,self.y as i64); 48 | }, 49 | _=>{}, 50 | } 51 | } 52 | #[allow(non_snake_case)] 53 | fn onClick(self,canvas:&Canvas)->bool{ 54 | if canvas.mouseClick()==MouseButton::Left && (canvas.mouseX()>self.x && canvas.mouseX()self.y && canvas.mouseY()bool{ 61 | if canvas.mouseClick()!=MouseButton::Left && (canvas.mouseX()>self.x && canvas.mouseX()self.y && canvas.mouseY()Button{ 69 | Button{color:Color::from(190), x,y,width:40,height:20,border_width:2,style:Styles::Normal,text,} 70 | } 71 | pub fn location(&mut self,x:u16,y:u16)->Self{ 72 | self.x = x; 73 | self.y = y; 74 | *self 75 | } 76 | pub fn get_location(self)->(u16,u16){ 77 | (self.x,self.y) 78 | } 79 | pub fn get_x(self)->u16{ 80 | self.x 81 | } 82 | pub fn get_y(self)->u16{ 83 | self.y 84 | } 85 | pub fn color(&mut self,color:Color)->Self{ 86 | self.color = color; 87 | *self 88 | } 89 | pub fn size(&mut self,width:u16,height:u16)->Self{ 90 | self.width = width; 91 | self.height= height; 92 | *self 93 | } 94 | pub fn get_size(self)->(u16,u16){ 95 | (self.width,self.height) 96 | } 97 | pub fn get_width(self)->u16{ 98 | self.width 99 | } 100 | pub fn get_height(self)->u16{ 101 | self.height 102 | } 103 | pub fn width(&mut self,width:u16)->Self{ 104 | self.width = width; 105 | *self 106 | } 107 | pub fn height(&mut self,height:u16)->Self{ 108 | self.height = height; 109 | *self 110 | } 111 | 112 | pub fn border_width(&mut self,width:u8)->Self{ 113 | self.border_width = width; 114 | *self 115 | } 116 | pub fn get_border_width(self)->u8{ 117 | self.border_width 118 | } 119 | pub fn button_text(&mut self,text:&'static str)->Self{ 120 | self.text = text; 121 | *self 122 | } 123 | pub fn get_color(self)->Color{ 124 | self.color 125 | } 126 | pub fn style(&mut self,style:Styles)->Self{ 127 | self.style = style; 128 | *self 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/fonts.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Copy, PartialEq)] 2 | pub enum Fonts{ 3 | RobotoBlack, 4 | OpenSansBold, 5 | RobotoMedium, 6 | OpenSansExtraBold, 7 | RobotoCondensedItalic, 8 | OpenSansExtraBoldItalic, 9 | RobotoThinItalic, 10 | RobotoThin, 11 | DejaVuSans, 12 | RobotoBold, 13 | OpenSansRegular, 14 | OpenSansSemibold, 15 | OpenSansLight, 16 | RobotoRegular, 17 | RobotoCondensedRegular, 18 | RobotoCondensedBold, 19 | RobotoCondensedLightItalic, 20 | OpenSansItalic, 21 | OpenSansBoldItalic, 22 | OpenSansSemiboldItalic, 23 | RobotoItalic, 24 | OpenSansLightItalic, 25 | RobotoCondensedBoldItalic, 26 | RobotoMediumItalic, 27 | RobotoBoldItalic, 28 | RobotoCondensedLight, 29 | RobotoLight, 30 | RobotoLightItalic, 31 | RobotoBlackItalic, 32 | } 33 | impl Fonts{ 34 | pub fn get_ttf(self)->&'static [u8]{ 35 | match self{ 36 | Fonts::RobotoBlack=>{ let ttf1 = include_bytes!( "fonts/Roboto-Black.ttf"); 37 | return ttf1;}, 38 | Fonts::OpenSansBold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Bold.ttf"); 39 | return ttf1;}, 40 | Fonts::RobotoMedium=>{ let ttf1 = include_bytes!( "fonts/Roboto-Medium.ttf"); 41 | return ttf1;}, 42 | Fonts::OpenSansExtraBold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-ExtraBold.ttf"); 43 | return ttf1;}, 44 | Fonts::RobotoCondensedItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Italic.ttf"); 45 | return ttf1;}, 46 | Fonts::OpenSansExtraBoldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-ExtraBoldItalic.ttf"); 47 | return ttf1;}, 48 | Fonts::RobotoThinItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-ThinItalic.ttf"); 49 | return ttf1;}, 50 | Fonts::RobotoThin=>{ let ttf1 = include_bytes!( "fonts/Roboto-Thin.ttf"); 51 | return ttf1;}, 52 | Fonts::DejaVuSans=>{ let ttf1 = include_bytes!( "fonts/DejaVuSans.ttf"); 53 | return ttf1;}, 54 | Fonts::RobotoBold=>{ let ttf1 = include_bytes!( "fonts/Roboto-Bold.ttf"); 55 | return ttf1;}, 56 | Fonts::OpenSansRegular=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Regular.ttf"); 57 | return ttf1;}, 58 | Fonts::OpenSansSemibold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Semibold.ttf"); 59 | return ttf1;}, 60 | Fonts::OpenSansLight=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Light.ttf"); 61 | return ttf1;}, 62 | Fonts::RobotoRegular=>{ let ttf1 = include_bytes!( "fonts/Roboto-Regular.ttf"); 63 | return ttf1;}, 64 | Fonts::RobotoCondensedRegular=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Regular.ttf"); 65 | return ttf1;}, 66 | Fonts::RobotoCondensedBold=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Bold.ttf"); 67 | return ttf1;}, 68 | Fonts::RobotoCondensedLightItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-LightItalic.ttf"); 69 | return ttf1;}, 70 | Fonts::OpenSansItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Italic.ttf"); 71 | return ttf1;}, 72 | Fonts::OpenSansBoldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-BoldItalic.ttf"); 73 | return ttf1;}, 74 | Fonts::OpenSansSemiboldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-SemiboldItalic.ttf"); 75 | return ttf1;}, 76 | Fonts::RobotoItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-Italic.ttf"); 77 | return ttf1;}, 78 | Fonts::OpenSansLightItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-LightItalic.ttf"); 79 | return ttf1;}, 80 | Fonts::RobotoCondensedBoldItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-BoldItalic.ttf"); 81 | return ttf1;}, 82 | Fonts::RobotoMediumItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-MediumItalic.ttf"); 83 | return ttf1;}, 84 | Fonts::RobotoBoldItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-BoldItalic.ttf"); 85 | return ttf1;}, 86 | Fonts::RobotoCondensedLight=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Light.ttf"); 87 | return ttf1;}, 88 | Fonts::RobotoLight=>{ let ttf1 = include_bytes!( "fonts/Roboto-Light.ttf"); 89 | return ttf1;}, 90 | Fonts::RobotoLightItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-LightItalic.ttf"); 91 | return ttf1;}, 92 | Fonts::RobotoBlackItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-BlackItalic.ttf"); 93 | return ttf1;}, 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/fonts/Apache License.txt: -------------------------------------------------------------------------------- 1 | Font data copyright Google 2012 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright [yyyy] [name of copyright owner] 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. -------------------------------------------------------------------------------- /src/fonts/DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/DejaVuSans.ttf -------------------------------------------------------------------------------- /src/fonts/GreatVibes-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/GreatVibes-Regular.otf -------------------------------------------------------------------------------- /src/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /src/fonts/OpenSans-SemiboldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/OpenSans-SemiboldItalic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Black.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-BlackItalic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-BoldItalic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Italic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Light.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-LightItalic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-MediumItalic.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-Thin.ttf -------------------------------------------------------------------------------- /src/fonts/Roboto-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/Roboto-ThinItalic.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-Bold.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-BoldItalic.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-Italic.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-Light.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-LightItalic.ttf -------------------------------------------------------------------------------- /src/fonts/RobotoCondensed-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GuyL99/metropolis/1eac53f089b4cc30a8e6620f63cc21ea5e95f1b7/src/fonts/RobotoCondensed-Regular.ttf -------------------------------------------------------------------------------- /src/fonts/matches.txt: -------------------------------------------------------------------------------- 1 | match self{ 2 | Fonts::RobotoBlack=>{ let ttf1 = include_bytes!( "fonts/Roboto-Black.ttf"); 3 | return ttf1;}, 4 | Fonts::OpenSansBold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Bold.ttf"); 5 | return ttf1;}, 6 | Fonts::RobotoMedium=>{ let ttf1 = include_bytes!( "fonts/Roboto-Medium.ttf"); 7 | return ttf1;}, 8 | Fonts::OpenSansExtraBold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-ExtraBold.ttf"); 9 | return ttf1;}, 10 | Fonts::RobotoCondensedItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Italic.ttf"); 11 | return ttf1;}, 12 | Fonts::OpenSansExtraBoldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-ExtraBoldItalic.ttf"); 13 | return ttf1;}, 14 | Fonts::RobotoThinItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-ThinItalic.ttf"); 15 | return ttf1;}, 16 | Fonts::RobotoThin=>{ let ttf1 = include_bytes!( "fonts/Roboto-Thin.ttf"); 17 | return ttf1;}, 18 | Fonts::DejaVuSans=>{ let ttf1 = include_bytes!( "fonts/DejaVuSans.ttf"); 19 | return ttf1;}, 20 | Fonts::RobotoBold=>{ let ttf1 = include_bytes!( "fonts/Roboto-Bold.ttf"); 21 | return ttf1;}, 22 | Fonts::OpenSansRegular=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Regular.ttf"); 23 | return ttf1;}, 24 | Fonts::OpenSansSemibold=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Semibold.ttf"); 25 | return ttf1;}, 26 | Fonts::OpenSansLight=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Light.ttf"); 27 | return ttf1;}, 28 | Fonts::RobotoRegular=>{ let ttf1 = include_bytes!( "fonts/Roboto-Regular.ttf"); 29 | return ttf1;}, 30 | Fonts::RobotoCondensedRegular=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Regular.ttf"); 31 | return ttf1;}, 32 | Fonts::RobotoCondensedBold=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Bold.ttf"); 33 | return ttf1;}, 34 | Fonts::RobotoCondensedLightItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-LightItalic.ttf"); 35 | return ttf1;}, 36 | Fonts::OpenSansItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-Italic.ttf"); 37 | return ttf1;}, 38 | Fonts::OpenSansBoldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-BoldItalic.ttf"); 39 | return ttf1;}, 40 | Fonts::OpenSansSemiboldItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-SemiboldItalic.ttf"); 41 | return ttf1;}, 42 | Fonts::RobotoItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-Italic.ttf"); 43 | return ttf1;}, 44 | Fonts::OpenSansLightItalic=>{ let ttf1 = include_bytes!( "fonts/OpenSans-LightItalic.ttf"); 45 | return ttf1;}, 46 | Fonts::RobotoCondensedBoldItalic=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-BoldItalic.ttf"); 47 | return ttf1;}, 48 | Fonts::RobotoMediumItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-MediumItalic.ttf"); 49 | return ttf1;}, 50 | Fonts::RobotoBoldItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-BoldItalic.ttf"); 51 | return ttf1;}, 52 | Fonts::RobotoCondensedLight=>{ let ttf1 = include_bytes!( "fonts/RobotoCondensed-Light.ttf"); 53 | return ttf1;}, 54 | Fonts::RobotoLight=>{ let ttf1 = include_bytes!( "fonts/Roboto-Light.ttf"); 55 | return ttf1;}, 56 | Fonts::RobotoLightItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-LightItalic.ttf"); 57 | return ttf1;}, 58 | Fonts::RobotoBlackItalic=>{ let ttf1 = include_bytes!( "fonts/Roboto-BlackItalic.ttf"); 59 | return ttf1;}, 60 | } -------------------------------------------------------------------------------- /src/fonts/names.txt: -------------------------------------------------------------------------------- 1 | RobotoBlack, 2 | OpenSansBold, 3 | RobotoMedium, 4 | OpenSansExtraBold, 5 | RobotoCondensedItalic, 6 | OpenSansExtraBoldItalic, 7 | RobotoThinItalic, 8 | RobotoThin, 9 | DejaVuSans, 10 | RobotoBold, 11 | OpenSansRegular, 12 | OpenSansSemibold, 13 | OpenSansLight, 14 | RobotoRegular, 15 | RobotoCondensedRegular, 16 | RobotoCondensedBold, 17 | RobotoCondensedLightItalic, 18 | OpenSansItalic, 19 | OpenSansBoldItalic, 20 | OpenSansSemiboldItalic, 21 | RobotoItalic, 22 | OpenSansLightItalic, 23 | RobotoCondensedBoldItalic, 24 | RobotoMediumItalic, 25 | RobotoBoldItalic, 26 | RobotoCondensedLight, 27 | RobotoLight, 28 | RobotoLightItalic, 29 | RobotoBlackItalic, 30 | -------------------------------------------------------------------------------- /src/fonts/scrpt1.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | with open("matches.txt","a") as f: 4 | f.write("match self{\n") 5 | for font in os.listdir(): 6 | with open("matches.txt","a") as ff: 7 | font1 = font.split('.') 8 | #print(font) 9 | if font1[1]=='ttf': 10 | font2 = font1[0] 11 | '''ff.write("\t\t\t") 12 | ff.write(font1[0].replace('-','')) 13 | ff.write(",\n")''' 14 | ff.write("\tFonts::") 15 | ff.write(font2.replace('-','')) 16 | ff.write("=>{ let ttf1 = include_bytes!( \"fonts/") 17 | ff.write(font1[0]) 18 | ff.write(".ttf\");\n") 19 | ff.write("\treturn ttf1;},") 20 | ff.write("\n") 21 | with open("matches.txt","a") as fff: 22 | fff.write("}") 23 | 24 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //!this crate is a high level easy to use graphics renderer inspired by processing in java and p5 in 2 | //!javascript. Working with it utilizes high level function like arc,line,rect and such that are 3 | //!you to make sveral canvases and display them as you wish. 3D is also coming and is currently 4 | //!under development(for now it's just 2D functions). 5 | //!the way to use the library is to use the size function to create a canvas with a fixed 6 | //!size(width,height), afterwards, you create some setup variable and setup the background for the 7 | //!animation/game/test/simulation you want to run, then you create a closure and save it to a variable, 8 | //!and finally send it to the show function(designed to loop over the draw function). 9 | //!like this (grvaity example): 10 | //!``` 11 | //!use metropolis::*; 12 | //!use metropolis::color::*; 13 | //!fn main() { 14 | //! //here I set up the background, height, width,spd,and the position on y 15 | //! let height = 900; 16 | //! let width = 1200; 17 | //! size(width,height); 18 | //! let mut spd = 0; 19 | //! let mut posy = 0; 20 | //! background(grayscale(100)); 21 | //! let draw =move || { 22 | //! //inside the draw function I create the accelaration to simulate gravity 23 | //! spd+=1; 24 | //! if posy+50< height{ 25 | //! posy+=spd; 26 | //! } 27 | //! // and those are the library functions fill-which makes the filled color be pinkish 28 | //! // and circle which draws a circle with a center in 400(in x) and posy(changing y), with a 29 | //! //radius of 100. 30 | //! fill(rgb(255,0,100)); 31 | //! circle(400,posy,100); 32 | //! }; 33 | //! //finally I send the draw function into show like that(should be used without the commenting, 34 | //! //it's commented because it loopes over with no timeout 35 | //! //show(draw); 36 | //!} 37 | //!``` 38 | //!or you can do something similar only with a safe canvas struct(take your pick for your use case: 39 | //!the public canvas struct(there is actually an inner one for the static functions). it is 40 | //!``` 41 | //!use metropolis::color::*; 42 | //!use metropolis::canvas::Canvas; 43 | //!fn main(){ 44 | //! let height = 600; 45 | //! let width = 800; 46 | //! //size(width, height); 47 | //! let mut canv:Canvas= Canvas::new(width,height); 48 | //! canv.background(grayscale(100)); 49 | //! let draw = |mut canvas:Canvas|->Canvas { 50 | //! let curve_vec: Vec<[i64; 2]> = vec![ 51 | //! [0, 400], 52 | //! [30, 370], 53 | //! [50, 300], 54 | //! [75, 257], 55 | //! [80, 240], 56 | //! [150, 150], 57 | //! [250, 050], 58 | //! ]; 59 | //! canvas.bezierCurve(curve_vec); 60 | //! canvas 61 | //! }; 62 | //! canv.show(draw); 63 | //!} 64 | //!``` 65 | //!as you may see the draw loop is designed a bit different. 66 | mod vertex; 67 | use vertex::*; 68 | mod mapping; 69 | mod setup; 70 | mod shaders; 71 | use mapping::*; 72 | ///the canvas mod contains the canvas and image structs used to create multiple and multithreading 73 | ///safe canvases 74 | pub mod canvas; 75 | pub use canvas::*; 76 | mod text; 77 | mod compute; 78 | mod canvas_glob; 79 | use canvas_glob::*; 80 | ///a module used for coloring in this crate, will be adding more functions and easier set in the 81 | ///future. 82 | pub mod color; 83 | //pub mod page; 84 | ///a module to provide some mathematical help functions from the crate. 85 | ///Will be much expanded upon in the near future. 86 | pub mod vector; 87 | pub mod math; 88 | pub mod elements; 89 | pub mod fonts; 90 | use color::*; 91 | use math::{bezier_points, catmull_rom_chain}; 92 | pub static mut FPS:f32 = 0f32; 93 | pub static mut HEIGHT:u16 = 0u16; 94 | pub static mut WIDTH:u16 = 0u16; 95 | use vulkano::image::Dimensions; 96 | use png; 97 | use std::fs::File; 98 | pub use winit::VirtualKeyCode as keyCode; 99 | pub use winit::MouseButton; 100 | use winit::ModifiersState; 101 | fn add_to_text(pusher: Stext) { 102 | unsafe { 103 | match &TEXT_VEC { 104 | None => { 105 | TEXT_VEC = Some(vec![pusher]); 106 | } 107 | Some(vec1) => { 108 | let mut vec2 = vec1.clone(); 109 | vec2.push(pusher); 110 | TEXT_VEC = Some(vec2); 111 | } 112 | }; 113 | } 114 | } 115 | fn add_to_fill(pusher: Vertex) { 116 | unsafe { 117 | match &FILL_VERTECIES { 118 | None => { 119 | FILL_VERTECIES = Some(vec![pusher]); 120 | } 121 | Some(vec1) => { 122 | let mut vec2 = vec1.clone(); 123 | vec2.push(pusher); 124 | FILL_VERTECIES = Some(vec2); 125 | } 126 | }; 127 | } 128 | } 129 | fn add_to_stroke(pusher: Vertex) { 130 | unsafe { 131 | match &STROKE_VERTECIES { 132 | None => { 133 | STROKE_VERTECIES = Some(vec![pusher]); 134 | } 135 | Some(vec1) => { 136 | let mut vec2 = vec1.clone(); 137 | vec2.push(pusher); 138 | STROKE_VERTECIES = Some(vec2); 139 | } 140 | }; 141 | } 142 | } 143 | ///keeps the key pressed in the key event until a new key is pressed 144 | #[allow(non_snake_case)] 145 | pub fn lockKeyEvent(){ 146 | unsafe{ 147 | CANVAS.key.keep_key = true; 148 | } 149 | } 150 | ///returns the x scroll delta of the mouse 151 | #[allow(non_snake_case)] 152 | pub fn mouseScrollX()->i64{ 153 | unsafe{ 154 | CANVAS.mouse_scroll.delta_x() 155 | } 156 | } 157 | ///returns the y scroll delta of the mouse 158 | #[allow(non_snake_case)] 159 | pub fn mouseScrollY()->i64{ 160 | unsafe{ 161 | CANVAS.mouse_scroll.delta_y() 162 | } 163 | } 164 | ///returns the current key that is pressed on the mouse. 165 | #[allow(non_snake_case)] 166 | pub fn mouseClick()->MouseButton{ 167 | unsafe{ 168 | match CANVAS.mouse.btn{ 169 | Some(btn)=> {return btn;}, 170 | None=> {return MouseButton::Other(99);} 171 | } 172 | } 173 | } 174 | ///returns the x position of the mouse 175 | #[allow(non_snake_case)] 176 | pub fn mouseX()->u16{ 177 | unsafe{ 178 | CANVAS.cursor_pos.0 179 | } 180 | } 181 | ///returns the y position of the mouse 182 | #[allow(non_snake_case)] 183 | pub fn mouseY()->u16{ 184 | unsafe{ 185 | CANVAS.cursor_pos.1 186 | } 187 | } 188 | ///creates the canvas with the width and height sent to this function 189 | pub fn size(width: u16, height: u16) { 190 | unsafe { 191 | CANVAS.size = (width, height); 192 | } 193 | } 194 | ///returns the current key that is pressed. 195 | #[allow(non_snake_case)] 196 | pub fn keyPressed()->keyCode{ 197 | unsafe{ 198 | match CANVAS.key.keycode{ 199 | Some(key)=> {return key;}, 200 | None=> {return keyCode::Power;} 201 | } 202 | } 203 | } 204 | ///returns the current state of the modifiers 205 | pub fn get_modifiers()->ModifiersState{ 206 | unsafe{ 207 | CANVAS.key.get_mod() 208 | } 209 | } 210 | ///recieves f32 ext size and sets the canvases text_size to that size 211 | #[allow(non_snake_case)] 212 | pub fn textSize(sz:u8) { 213 | unsafe { 214 | CANVAS.text_size = sz as f32; 215 | } 216 | } 217 | ///this is the function used to run the animation 218 | pub fn show(draw_fn: F) 219 | where 220 | F: FnMut() + 'static, 221 | { 222 | unsafe { 223 | CANVAS.show(draw_fn); 224 | } 225 | } 226 | ///recieves the x and y of the top spot and then the width and height of the rectangle you want 227 | ///built. 228 | pub fn rect(x: u16, y: u16, width: u16, height: u16) { 229 | unsafe { 230 | let scale = [CANVAS.size.0, CANVAS.size.1]; 231 | let t_l = map([x, y], scale); 232 | let b_r = map([x + width, y + height], scale); 233 | let t_r = map([x + width, y], scale); 234 | let b_l = map([x, y + height], scale); 235 | if CANVAS.fill { 236 | let color = CANVAS.fill_color; 237 | add_to_fill(Vertex { 238 | position: b_r, 239 | color, 240 | tex_coords:[0f32,0f32], 241 | }); 242 | add_to_fill(Vertex { 243 | position: t_r, 244 | color, 245 | tex_coords:[0f32,0f32], 246 | }); 247 | add_to_fill(Vertex { 248 | position: t_l, 249 | color, 250 | tex_coords:[0f32,0f32], 251 | }); 252 | add_to_fill(Vertex { 253 | position: t_l, 254 | color, 255 | tex_coords:[0f32,0f32], 256 | }); 257 | add_to_fill(Vertex { 258 | position: b_l, 259 | color, 260 | tex_coords:[0f32,0f32], 261 | }); 262 | add_to_fill(Vertex { 263 | position: b_r, 264 | color, 265 | tex_coords:[0f32,0f32], 266 | }); 267 | } 268 | if CANVAS.stroke { 269 | let color = CANVAS.color; 270 | add_to_stroke(Vertex { 271 | position: t_l, 272 | color, 273 | tex_coords:[0f32,0f32], 274 | }); 275 | add_to_stroke(Vertex { 276 | position: t_r, 277 | color, 278 | tex_coords:[0f32,0f32], 279 | }); 280 | add_to_stroke(Vertex { 281 | position: t_r, 282 | color, 283 | tex_coords:[0f32,0f32], 284 | }); 285 | add_to_stroke(Vertex { 286 | position: b_r, 287 | color, 288 | tex_coords:[0f32,0f32], 289 | }); 290 | add_to_stroke(Vertex { 291 | position: b_r, 292 | color, 293 | tex_coords:[0f32,0f32], 294 | }); 295 | add_to_stroke(Vertex { 296 | position: b_l, 297 | color, 298 | tex_coords:[0f32,0f32], 299 | }); 300 | add_to_stroke(Vertex { 301 | position: b_l, 302 | color, 303 | tex_coords:[0f32,0f32], 304 | }); 305 | add_to_stroke(Vertex { 306 | position: t_l, 307 | color, 308 | tex_coords:[0f32,0f32], 309 | }); 310 | } 311 | } 312 | } 313 | ///recieves the x and y of the top spot and then the width of the sqaure you want built. 314 | pub fn square(x: u16, y: u16, width: u16) { 315 | unsafe { 316 | let scale = [CANVAS.size.0, CANVAS.size.1]; 317 | let t_l = map([x, y], scale); 318 | let b_r = map([x + width, y + width], scale); 319 | let t_r = map([x + width, y], scale); 320 | let b_l = map([x, y + width], scale); 321 | if CANVAS.fill { 322 | let color = CANVAS.fill_color; 323 | add_to_fill(Vertex { 324 | position: b_r, 325 | color, 326 | tex_coords:[0f32,0f32], 327 | }); 328 | add_to_fill(Vertex { 329 | position: t_r, 330 | color, 331 | tex_coords:[0f32,0f32], 332 | }); 333 | add_to_fill(Vertex { 334 | position: t_l, 335 | color, 336 | tex_coords:[0f32,0f32], 337 | }); 338 | add_to_fill(Vertex { 339 | position: t_l, 340 | color, 341 | tex_coords:[0f32,0f32], 342 | }); 343 | add_to_fill(Vertex { 344 | position: b_l, 345 | color, 346 | tex_coords:[0f32,0f32], 347 | }); 348 | add_to_fill(Vertex { 349 | position: b_r, 350 | color, 351 | tex_coords:[0f32,0f32], 352 | }); 353 | } 354 | if CANVAS.stroke { 355 | let color = CANVAS.color; 356 | add_to_stroke(Vertex { 357 | position: t_l, 358 | color, 359 | tex_coords:[0f32,0f32], 360 | }); 361 | add_to_stroke(Vertex { 362 | position: t_r, 363 | color, 364 | tex_coords:[0f32,0f32], 365 | }); 366 | add_to_stroke(Vertex { 367 | position: t_r, 368 | color, 369 | tex_coords:[0f32,0f32], 370 | }); 371 | add_to_stroke(Vertex { 372 | position: b_r, 373 | color, 374 | tex_coords:[0f32,0f32], 375 | }); 376 | add_to_stroke(Vertex { 377 | position: b_l, 378 | color, 379 | tex_coords:[0f32,0f32], 380 | }); 381 | add_to_stroke(Vertex { 382 | position: b_l, 383 | color, 384 | tex_coords:[0f32,0f32], 385 | }); 386 | add_to_stroke(Vertex { 387 | position: t_l, 388 | color, 389 | tex_coords:[0f32,0f32], 390 | }); 391 | } 392 | } 393 | } 394 | ///recieves the x and y of the top point and then the x and the y of the bottom point and creates a 395 | ///line between them. 396 | pub fn line(x: u16, y: u16, x2: u16, y2: u16) { 397 | unsafe { 398 | let scale = [CANVAS.size.0, CANVAS.size.1]; 399 | let srt = map([x, y], scale); 400 | let fin = map([x2, y2], scale); 401 | let color = CANVAS.color; 402 | add_to_stroke(Vertex { 403 | position: srt, 404 | color, 405 | tex_coords:[0f32,0f32], 406 | }); 407 | add_to_stroke(Vertex { 408 | position: fin, 409 | color, 410 | tex_coords:[0f32,0f32], 411 | }); 412 | } 413 | } 414 | ///recieves the x and y of the 3 points of the triangle and creates it based on them 415 | pub fn triangle(x1: u16, y1: u16, x2: u16, y2: u16, x3: u16, y3: u16) { 416 | unsafe { 417 | let scale = [CANVAS.size.0, CANVAS.size.1]; 418 | let pt1 = map([x1, y1], scale); 419 | let pt2 = map([x2, y2], scale); 420 | let pt3 = map([x3, y3], scale); 421 | if CANVAS.fill { 422 | let color = CANVAS.fill_color; 423 | add_to_fill(Vertex { 424 | position: pt1, 425 | color, 426 | tex_coords:[0f32,0f32], 427 | }); 428 | add_to_fill(Vertex { 429 | position: pt2, 430 | color, 431 | tex_coords:[0f32,0f32], 432 | }); 433 | add_to_fill(Vertex { 434 | position: pt3, 435 | color, 436 | tex_coords:[0f32,0f32], 437 | }); 438 | } 439 | if CANVAS.stroke { 440 | let color = CANVAS.color; 441 | add_to_stroke(Vertex { 442 | position: pt1, 443 | color, 444 | tex_coords:[0f32,0f32], 445 | }); 446 | add_to_stroke(Vertex { 447 | position: pt2, 448 | color, 449 | tex_coords:[0f32,0f32], 450 | }); 451 | add_to_stroke(Vertex { 452 | position: pt2, 453 | color, 454 | tex_coords:[0f32,0f32], 455 | }); 456 | add_to_stroke(Vertex { 457 | position: pt3, 458 | color, 459 | tex_coords:[0f32,0f32], 460 | }); 461 | add_to_stroke(Vertex { 462 | position: pt3, 463 | color, 464 | tex_coords:[0f32,0f32], 465 | }); 466 | add_to_stroke(Vertex { 467 | position: pt1, 468 | color, 469 | tex_coords:[0f32,0f32], 470 | }); 471 | } 472 | } 473 | } 474 | ///recieves the x and y of the 4 points of the quad and creates it based on them 475 | pub fn quad(x1: u16, y1: u16, x2: u16, y2: u16, x3: u16, y3: u16, x4: u16, y4: u16) { 476 | unsafe { 477 | let scale = [CANVAS.size.0, CANVAS.size.1]; 478 | let pt1 = map([x1, y1], scale); 479 | let pt2 = map([x2, y2], scale); 480 | let pt3 = map([x3, y3], scale); 481 | let pt4 = map([x4, y4], scale); 482 | if CANVAS.fill { 483 | let color = CANVAS.fill_color; 484 | add_to_fill(Vertex { 485 | position: pt1, 486 | color, 487 | tex_coords:[0f32,0f32], 488 | }); 489 | add_to_fill(Vertex { 490 | position: pt2, 491 | color, 492 | tex_coords:[0f32,0f32], 493 | }); 494 | add_to_fill(Vertex { 495 | position: pt3, 496 | color, 497 | tex_coords:[0f32,0f32], 498 | }); 499 | add_to_fill(Vertex { 500 | position: pt4, 501 | color, 502 | tex_coords:[0f32,0f32], 503 | }); 504 | } 505 | if CANVAS.stroke { 506 | let color = CANVAS.color; 507 | add_to_stroke(Vertex { 508 | position: pt1, 509 | color, 510 | tex_coords:[0f32,0f32], 511 | }); 512 | add_to_stroke(Vertex { 513 | position: pt2, 514 | color, 515 | tex_coords:[0f32,0f32], 516 | }); 517 | add_to_stroke(Vertex { 518 | position: pt2, 519 | color, 520 | tex_coords:[0f32,0f32], 521 | }); 522 | add_to_stroke(Vertex { 523 | position: pt3, 524 | color, 525 | tex_coords:[0f32,0f32], 526 | }); 527 | add_to_stroke(Vertex { 528 | position: pt3, 529 | color, 530 | tex_coords:[0f32,0f32], 531 | }); 532 | add_to_stroke(Vertex { 533 | position: pt4, 534 | color, 535 | tex_coords:[0f32,0f32], 536 | }); 537 | add_to_stroke(Vertex { 538 | position: pt4, 539 | color, 540 | tex_coords:[0f32,0f32], 541 | }); 542 | add_to_stroke(Vertex { 543 | position: pt1, 544 | color, 545 | tex_coords:[0f32,0f32], 546 | }); 547 | } 548 | } 549 | } 550 | ///recieves the x and the y of the center of the ellipse and the width and height of the ellipse 551 | ///and creates it accordingly 552 | pub fn ellipse(x: u16, y: u16, a: u16, b: u16) { 553 | unsafe { 554 | let scale = [CANVAS.size.0, CANVAS.size.1]; 555 | if CANVAS.stroke && !(CANVAS.fill && CANVAS.color == CANVAS.fill_color) { 556 | let mut pt_x = x as f32 + a as f32; 557 | let mut pt_y = y as f32; 558 | for an in (0..360).step_by(6) { 559 | let ptx = x as f32 + ((an as f32 / 360.0) * 6.28).cos() * a as f32; 560 | let pty = y as f32 + ((an as f32 / 360.0) * 6.28).sin() * b as f32; 561 | add_to_stroke(Vertex { 562 | position: map_circ([pt_x, pt_y], scale), 563 | color: CANVAS.color, 564 | tex_coords:[0f32,0f32], 565 | }); 566 | add_to_stroke(Vertex { 567 | position: map_circ([ptx, pty], scale), 568 | color: CANVAS.color, 569 | tex_coords:[0f32,0f32], 570 | }); 571 | pt_x = ptx; 572 | pt_y = pty; 573 | } 574 | add_to_stroke(Vertex { 575 | position: map_circ([pt_x, pt_y], scale), 576 | color: CANVAS.color, 577 | tex_coords:[0f32,0f32], 578 | }); 579 | pt_x = x as f32 + a as f32 + 0.5; 580 | pt_y = y as f32 + 0.5; 581 | add_to_stroke(Vertex { 582 | position: map_circ([pt_x, pt_y], scale), 583 | color: CANVAS.color, 584 | tex_coords:[0f32,0f32], 585 | }); 586 | } 587 | if CANVAS.fill { 588 | let mut pt_x = x as f32 + a as f32; 589 | let mut pt_y = y as f32; 590 | for an in (0..360).step_by(6) { 591 | let ptx = x as f32 + ((an as f32 / 360.0) * 6.28).cos() * a as f32; 592 | let pty = y as f32 + ((an as f32 / 360.0) * 6.28).sin() * b as f32; 593 | add_to_fill(Vertex { 594 | position: map_circ([pt_x, pt_y], scale), 595 | color: CANVAS.fill_color, 596 | tex_coords:[0f32,0f32], 597 | }); 598 | add_to_fill(Vertex { 599 | position: map_circ([ptx, pty], scale), 600 | color: CANVAS.fill_color, 601 | tex_coords:[0f32,0f32], 602 | }); 603 | add_to_fill(Vertex { 604 | position: map_circ([x as f32, y as f32], scale), 605 | color: CANVAS.fill_color, 606 | tex_coords:[0f32,0f32], 607 | }); 608 | pt_x = ptx; 609 | pt_y = pty; 610 | } 611 | add_to_fill(Vertex { 612 | position: map_circ([pt_x, pt_y], scale), 613 | color: CANVAS.fill_color, 614 | tex_coords:[0f32,0f32], 615 | }); 616 | pt_x = x as f32 + a as f32 + 0.5; 617 | pt_y = y as f32 + 0.5; 618 | add_to_fill(Vertex { 619 | position: map_circ([pt_x, pt_y], scale), 620 | color: CANVAS.fill_color, 621 | tex_coords:[0f32,0f32], 622 | }); 623 | add_to_fill(Vertex { 624 | position: map_circ([x as f32, y as f32], scale), 625 | color: CANVAS.fill_color, 626 | tex_coords:[0f32,0f32], 627 | }); 628 | } 629 | } 630 | } 631 | ///recieves the x and y of the center of the circle and the radius and builds it with them. 632 | pub fn circle(x: u16, y: u16, rad: u16) { 633 | unsafe { 634 | let scale = [CANVAS.size.0, CANVAS.size.1]; 635 | if CANVAS.stroke && !(CANVAS.fill && CANVAS.color == CANVAS.fill_color) { 636 | let mut pt_x = x as f32 + rad as f32; 637 | let mut pt_y = y as f32; 638 | for a in (0..360).step_by(6) { 639 | let ptx = x as f32 + ((a as f32 / 360.0) * 6.28).cos() * rad as f32; 640 | let pty = y as f32 + ((a as f32 / 360.0) * 6.28).sin() * rad as f32; 641 | add_to_stroke(Vertex { 642 | position: map_circ([pt_x, pt_y], scale), 643 | color: CANVAS.color, 644 | tex_coords:[0f32,0f32], 645 | }); 646 | add_to_stroke(Vertex { 647 | position: map_circ([ptx, pty], scale), 648 | color: CANVAS.color, 649 | tex_coords:[0f32,0f32], 650 | }); 651 | pt_x = ptx; 652 | pt_y = pty; 653 | } 654 | add_to_stroke(Vertex { 655 | position: map_circ([pt_x, pt_y], scale), 656 | color: CANVAS.color, 657 | tex_coords:[0f32,0f32], 658 | }); 659 | pt_x = x as f32 + rad as f32 + 0.5; 660 | pt_y = y as f32 + 0.5; 661 | add_to_stroke(Vertex { 662 | position: map_circ([pt_x, pt_y], scale), 663 | color: CANVAS.color, 664 | tex_coords:[0f32,0f32], 665 | }); 666 | } 667 | if CANVAS.fill { 668 | let mut pt_x = x as f32 + rad as f32; 669 | let mut pt_y = y as f32; 670 | for a in (0..360).step_by(6) { 671 | let ptx = x as f32 + ((a as f32 / 360.0) * 6.28).cos() * rad as f32; 672 | let pty = y as f32 + ((a as f32 / 360.0) * 6.28).sin() * rad as f32; 673 | add_to_fill(Vertex { 674 | position: map_circ([pt_x, pt_y], scale), 675 | color: CANVAS.fill_color, 676 | tex_coords:[0f32,0f32], 677 | }); 678 | add_to_fill(Vertex { 679 | position: map_circ([ptx, pty], scale), 680 | color: CANVAS.fill_color, 681 | tex_coords:[0f32,0f32], 682 | }); 683 | add_to_fill(Vertex { 684 | position: map_circ([x as f32, y as f32], scale), 685 | color: CANVAS.fill_color, 686 | tex_coords:[0f32,0f32], 687 | }); 688 | pt_x = ptx; 689 | pt_y = pty; 690 | } 691 | add_to_fill(Vertex { 692 | position: map_circ([pt_x, pt_y], scale), 693 | color: CANVAS.fill_color, 694 | tex_coords:[0f32,0f32], 695 | }); 696 | pt_x = x as f32 + rad as f32 + 0.5; 697 | pt_y = y as f32 + 0.5; 698 | add_to_fill(Vertex { 699 | position: map_circ([pt_x, pt_y], scale), 700 | color: CANVAS.fill_color, 701 | tex_coords:[0f32,0f32], 702 | }); 703 | add_to_fill(Vertex { 704 | position: map_circ([x as f32, y as f32], scale), 705 | color: CANVAS.fill_color, 706 | tex_coords:[0f32,0f32], 707 | }); 708 | } 709 | } 710 | } 711 | ///recieves the x and the y and makes a small circle in the spot(size depends on strokeWeight). 712 | pub fn point(x: u16, y: u16) { 713 | unsafe { 714 | let stro = CANVAS.stroke; 715 | let fil = CANVAS.fill; 716 | CANVAS.stroke = false; 717 | CANVAS.fill = true; 718 | circle(x, y, CANVAS.stroke_weight as u16); 719 | CANVAS.stroke = stro; 720 | CANVAS.fill = fil; 721 | } 722 | } 723 | ///enables fill and receives the color of the fill(the struct color) and sets the fill color to be 724 | ///the color. 725 | pub fn fill(color: Color) { 726 | let r = color.get_r(); 727 | let g = color.get_g(); 728 | let b = color.get_b(); 729 | let a = color.get_a(); 730 | unsafe { 731 | CANVAS.fill = true; 732 | CANVAS.fill_color = mapping::map_colors([r, g, b, a]); 733 | } 734 | } 735 | ///enables stroke and receives the color of the stroke(the struct color) and sets the stroke color to be 736 | ///the color. 737 | pub fn stroke(color: Color) { 738 | let r = color.get_r(); 739 | let g = color.get_g(); 740 | let b = color.get_b(); 741 | let a = color.get_a(); 742 | unsafe { 743 | CANVAS.stroke = true; 744 | CANVAS.color = mapping::map_colors([r, g, b, a]); 745 | } 746 | } 747 | ///sets the background color(using the color struct). 748 | pub fn background(color: Color) { 749 | let r = color.get_r(); 750 | let g = color.get_g(); 751 | let b = color.get_b(); 752 | let a = color.get_a(); 753 | unsafe { 754 | CANVAS.background_color = mapping::map_colors([r, g, b, a]); 755 | } 756 | } 757 | ///sets the stroke weight(the width of lines and points 758 | #[allow(non_snake_case)] 759 | pub fn strokeWeight(weight: u8) { 760 | unsafe { 761 | CANVAS.stroke_weight = weight; 762 | } 763 | } 764 | ///disables fill on the canvas. 765 | #[allow(non_snake_case)] 766 | pub fn noFill() { 767 | unsafe { 768 | CANVAS.fill = false; 769 | } 770 | } 771 | ///disables stroke on the canvas. 772 | #[allow(non_snake_case)] 773 | pub fn noStroke() { 774 | unsafe { 775 | CANVAS.stroke = false; 776 | } 777 | } 778 | ///create an arc from a circle, recieves the center of the circle and the radius and the degrees 779 | ///covered by the arc (360 degree arc is a full circle). 780 | pub fn arc(x: u16, y: u16, rad: u16, deg: u16) { 781 | unsafe { 782 | let scale = [CANVAS.size.0, CANVAS.size.1]; 783 | if CANVAS.stroke && !(CANVAS.fill && CANVAS.color == CANVAS.fill_color) { 784 | let mut pt_x = x as f32 + rad as f32; 785 | let mut pt_y = y as f32; 786 | for a in (0..deg + 6).step_by(6) { 787 | let ptx = x as f32 + ((a as f32 / 360.0) * 6.28).cos() * rad as f32; 788 | let pty = y as f32 + ((a as f32 / 360.0) * 6.28).sin() * rad as f32; 789 | add_to_stroke(Vertex { 790 | position: map_circ([pt_x, pt_y], scale), 791 | color: CANVAS.color, 792 | tex_coords:[0f32,0f32], 793 | }); 794 | add_to_stroke(Vertex { 795 | position: map_circ([ptx, pty], scale), 796 | color: CANVAS.color, 797 | tex_coords:[0f32,0f32], 798 | }); 799 | pt_x = ptx; 800 | pt_y = pty; 801 | } 802 | } 803 | if CANVAS.fill { 804 | let mut pt_x = x as f32 + rad as f32; 805 | let mut pt_y = y as f32; 806 | for a in (0..deg + 6).step_by(6) { 807 | let ptx = x as f32 + ((a as f32 / 360.0) * 6.28).cos() * rad as f32; 808 | let pty = y as f32 + ((a as f32 / 360.0) * 6.28).sin() * rad as f32; 809 | add_to_fill(Vertex { 810 | position: map_circ([pt_x, pt_y], scale), 811 | color: CANVAS.fill_color, 812 | tex_coords:[0f32,0f32], 813 | }); 814 | add_to_fill(Vertex { 815 | position: map_circ([ptx, pty], scale), 816 | color: CANVAS.fill_color, 817 | tex_coords:[0f32,0f32], 818 | }); 819 | add_to_fill(Vertex { 820 | position: map_circ([x as f32, y as f32], scale), 821 | color: CANVAS.fill_color, 822 | tex_coords:[0f32,0f32], 823 | }); 824 | pt_x = ptx; 825 | pt_y = pty; 826 | } 827 | } 828 | } 829 | } 830 | ///loopes over the array and uses curveVertex to create a bezier curve 831 | #[allow(non_snake_case)] 832 | pub fn bezierCurve(ptvec: Vec<[i64; 2]>) { 833 | for i in 0..(ptvec.len() - 3) { 834 | if (i + 1) % 4 == 0 || i == 0 { 835 | bezierCurveVertex( 836 | ptvec[i][0], 837 | ptvec[i][1], 838 | ptvec[i + 1][0], 839 | ptvec[i + 1][1], 840 | ptvec[i + 2][0], 841 | ptvec[i + 2][1], 842 | ptvec[i + 3][0], 843 | ptvec[i + 3][1], 844 | ); 845 | } 846 | } 847 | } 848 | ///loopes over the array and uses curveVertex to create a catmull rom chain curve 849 | pub fn curve(ptvec: Vec<[i64; 2]>) { 850 | for i in 0..(ptvec.len() - 3) { 851 | bezierCurveVertex( 852 | ptvec[i][0], 853 | ptvec[i][1], 854 | ptvec[i + 1][0], 855 | ptvec[i + 1][1], 856 | ptvec[i + 2][0], 857 | ptvec[i + 2][1], 858 | ptvec[i + 3][0], 859 | ptvec[i + 3][1], 860 | ); 861 | } 862 | } 863 | ///uses the catmull rom chain algorithm in order to create a curve 864 | #[allow(non_snake_case)] 865 | pub fn curveVertex(x1: i64, y1: i64, x2: i64, y2: i64, x3: i64, y3: i64, x4: i64, y4: i64) { 866 | let c = catmull_rom_chain(x1, y1, x2, y2, x3, y3, x4, y4); 867 | unsafe { 868 | let scale = [CANVAS.size.0, CANVAS.size.1]; 869 | for pt in c.iter() { 870 | add_to_stroke(Vertex { 871 | position: mapf(*pt, scale), 872 | color: CANVAS.color, 873 | tex_coords:[0f32,0f32], 874 | }); 875 | } 876 | } 877 | } 878 | ///uses the cubic bezier curve algorithm in order to create a curve 879 | #[allow(non_snake_case)] 880 | pub fn bezierCurveVertex(x1: i64, y1: i64, x2: i64, y2: i64, x3: i64, y3: i64, x4: i64, y4: i64) { 881 | let c = bezier_points(x1, y1, x2, y2, x3, y3, x4, y4); 882 | unsafe { 883 | let scale = [CANVAS.size.0, CANVAS.size.1]; 884 | let mut ptnxt = c[0]; 885 | for pt in c.iter() { 886 | add_to_stroke(Vertex { 887 | position: mapf(ptnxt, scale), 888 | color: CANVAS.color, 889 | tex_coords:[0f32,0f32], 890 | }); 891 | add_to_stroke(Vertex { 892 | position: mapf(*pt, scale), 893 | color: CANVAS.color, 894 | tex_coords:[0f32,0f32], 895 | }); 896 | ptnxt = *pt; 897 | } 898 | } 899 | } 900 | ///drawes a text of a certain color and locaion on the canvas 901 | pub fn text(x:u16,y:u16,text:&'static str){ 902 | unsafe{ 903 | add_to_text(Stext{ 904 | position: [x as f32,y as f32], 905 | color: CANVAS.color, 906 | text: text, 907 | }); 908 | } 909 | } 910 | ///This struct is meant for loading and saving the image once and not every frame 911 | #[derive(Clone)] 912 | pub struct Image{ 913 | pub image_data:Vec, 914 | pub dimensions:Dimensions, 915 | } 916 | ///takes a path to the image and loads it into an Image struct 917 | ///should strictly be used outside the draw loop! 918 | #[allow(non_snake_case)] 919 | pub fn img(path:&str)->Image{ 920 | let decoder = png::Decoder::new(File::open(path).unwrap()); 921 | let (info, mut reader) = decoder.read_info().unwrap(); 922 | let mut image_data = Vec::new(); 923 | image_data.resize((info.width * info.height * 4) as usize, 0); 924 | reader.next_frame(&mut image_data).unwrap(); 925 | let dimensions = Dimensions::Dim2d { width: info.width, height: info.height }; 926 | Image{image_data,dimensions} 927 | } 928 | impl Image{ 929 | ///this function shoould be used inside the draw loop, because it does not load an image, it 930 | ///simply displays a loaded image 931 | pub fn display(self,x:u16,y:u16){ 932 | unsafe { 933 | let scale = [CANVAS.size.0, CANVAS.size.1]; 934 | let _imsize = [self.dimensions.width() as u16,self.dimensions.height() as u16]; 935 | add_to_fill(Vertex { 936 | position: map([x,y], scale), 937 | color: CANVAS.color, 938 | //tex_coords: map_tex(map([x,y], scale),imsize), 939 | tex_coords: map([x,y], scale), 940 | }); 941 | add_to_fill(Vertex { 942 | position: map([x+(self.dimensions.width() as u16),y], scale), 943 | color: CANVAS.color, 944 | //tex_coords: map_tex(map([x+(self.dimensions.width() as u16),y], scale),imsize), 945 | tex_coords: map([x+(self.dimensions.width() as u16),y], scale), 946 | }); 947 | add_to_fill(Vertex { 948 | position: map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale), 949 | color: CANVAS.color, 950 | //tex_coords: map_tex(map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale),imsize), 951 | tex_coords: map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale), 952 | }); 953 | add_to_fill(Vertex { 954 | position: map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale), 955 | color: CANVAS.color, 956 | //tex_coords: map_tex(map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale),imsize), 957 | tex_coords: map([x+(self.dimensions.width() as u16),y+(self.dimensions.height() as u16)], scale), 958 | }); 959 | add_to_fill(Vertex { 960 | position: map([x,y], scale), 961 | color: CANVAS.color, 962 | //tex_coords: map_tex(map([x,y], scale),imsize), 963 | tex_coords: map([x,y], scale), 964 | }); 965 | add_to_fill(Vertex { 966 | position: map([x,y+(self.dimensions.height() as u16)], scale), 967 | color: CANVAS.color, 968 | //tex_coords: map_tex(map([x,(y+(self.dimensions.height() as u16))], scale),imsize), 969 | tex_coords: map([x,(y+(self.dimensions.height() as u16))], scale), 970 | }); 971 | //println!("pos:{:?}\ntex:{:?}",FILL_VERTECIES.clone().unwrap()[0].position,FILL_VERTECIES.clone().unwrap()[0].tex_coords); 972 | TEXTURE = Some((self.image_data,self.dimensions)); 973 | } 974 | } 975 | } 976 | -------------------------------------------------------------------------------- /src/mapping.rs: -------------------------------------------------------------------------------- 1 | pub fn map(point: [u16; 2], scale: [u16; 2]) -> [f32; 2] { 2 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Copy+Clone+PartialEq{ 3 | let new_point: [f32; 2] = [ 4 | (point[0] as f32 / scale[0] as f32), 5 | (point[1] as f32 / scale[1] as f32), 6 | ]; 7 | [(new_point[0] * 2.0) - 1.0, (new_point[1] * 2.0) - 1.0] 8 | } 9 | pub fn map_colors(color: [u8; 4]) -> [f32; 4] { 10 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Copy+Clone+PartialEq{ 11 | [ 12 | color[0] as f32 / 255.0, 13 | color[1] as f32 / 255.0, 14 | color[2] as f32 / 255.0, 15 | color[3] as f32 / 255.0, 16 | ] 17 | } 18 | pub fn map_circ(point: [f32; 2], scale: [u16; 2]) -> [f32; 2] { 19 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Copy+Clone+PartialEq{ 20 | let new_point: [f32; 2] = [(point[0] / scale[0] as f32), (point[1] / scale[1] as f32)]; 21 | [(new_point[0] * 2.0) - 1.0, (new_point[1] * 2.0) - 1.0] 22 | } 23 | pub fn mapf(point: [f64; 2], scale: [u16; 2]) -> [f32; 2] { 24 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Copy+Clone+PartialEq{ 25 | let new_point: [f32; 2] = [ 26 | (point[0] as f32 / scale[0] as f32), 27 | (point[1] as f32 / scale[1] as f32), 28 | ]; 29 | [(new_point[0] * 2.0) - 1.0, (new_point[1] * 2.0) - 1.0] 30 | } 31 | /*#[allow(dead_code)] 32 | pub fn map_tex(point: [f32; 2], scale: [u16; 2]) -> [f32; 2] { 33 | let new_point: [f32; 2] = [ 34 | (point[0]/ scale[0] as f32), 35 | (point[1]/ scale[1] as f32), 36 | ]; 37 | new_point 38 | }*/ 39 | pub fn map_tex(point: [f32; 2], scale: [u16; 2]) -> [f32; 2] { 40 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Copy+Clone+PartialEq{ 41 | let new_point: [f32; 2] = [ 42 | (point[0]/ scale[0] as f32), 43 | (point[1]/ scale[1] as f32), 44 | ]; 45 | [(new_point[0]), (new_point[1])] 46 | } 47 | -------------------------------------------------------------------------------- /src/math.rs: -------------------------------------------------------------------------------- 1 | use crate::compute::*; 2 | use crate::vector::*; 3 | use std::ops::Add; 4 | use std::ops::Div; 5 | use std::ops::Mul; 6 | use std::ops::Sub; 7 | ///converts degrees to radians 8 | /// 9 | ///``` 10 | ///use metropolis::math::*; 11 | ///assert_eq!(rad(90.0),PI/2.0); 12 | ///``` 13 | pub fn rad(x: f32) -> f32 { 14 | (x / 180.0) * PI 15 | } 16 | ///converts radians to degrees 17 | /// 18 | ///``` 19 | ///use metropolis::math::*; 20 | ///assert_eq!(deg(PI),180.0); 21 | ///``` 22 | pub fn deg(x: f32) -> f32 { 23 | x * 180.0 / PI 24 | } 25 | /* 26 | ///uses Taylor's series to determine sinus at the x, for now accepts f32, in the future also u/i 27 | pub fn sin(x: f32) -> f32 { 28 | #[allow(illegal_floating_point_literal_pattern)] 29 | match x { 30 | 90.0 => { 31 | return 1.0; 32 | } 33 | 0.0 => { 34 | return 0.0; 35 | } 36 | 30.0 => { 37 | return 0.5; 38 | } 39 | _ => { 40 | let ang = rad(x % 360.0); 41 | return ang - ang.powf(3.0) / 6.0 + ang.powf(5.0) / 120.0 - ang.powf(7.0) / 5040.0; 42 | } 43 | }; 44 | } 45 | /*pub fn cos(x:T) -> f32 46 | where T:Add+Sub+Div+Mul+Sub+Mul+Copy+Div+Copy+Add+Copy+Sub+Sub+Div+Copy+Clone+PartialEq+Ord{ 47 | //where T:Add+Sub+Div+Mul+Sub+Add+Div+Mul+Mul+Copy+Div+Copy+Add+Copy+Sub+Sub+Div+Copy+Clone+PartialEq+PartialOrd{ 48 | //where T:numerous{*/ 49 | ///uses sin(90-alpha) in order to calculate cosine 50 | pub fn cos(x: f32) -> f32 { 51 | if x <= 90.0 { 52 | return sin(90.0 - x); 53 | } else if x <= 18.0 { 54 | return -1.0 * sin(180.0 - x); 55 | } else if x <= 270.0 { 56 | return sin(270.0 - x); 57 | } else { 58 | return -1.0 * sin(360.0 - x); 59 | } 60 | } 61 | ///uses sin(x)/cos(x) in order to calculate tan(x) 62 | pub fn tan(x: f32) -> f32 { 63 | sin(x) / cos(x) 64 | }*/ 65 | ///calculates the factorial of a number 66 | /// 67 | ///``` 68 | ///use metropolis::math::*; 69 | ///assert_eq!(factorial(6),720); 70 | ///``` 71 | pub fn factorial(n: u64) -> u64 { 72 | real_factorial(n, 1) 73 | } 74 | fn real_factorial(n: u64, mut accume: u64) -> u64 { 75 | if n == 1 { 76 | return accume; 77 | } 78 | accume *= n; 79 | real_factorial(n - 1, accume) 80 | } 81 | /*///returns the absolute value of the number i number 82 | /// 83 | ///``` 84 | ///use metropolis::math::*; 85 | ///assert_eq!(abs(-1),1); 86 | ///``` 87 | pub fn abs(x: T) -> T 88 | where 89 | T: Copy + Clone + Add + Sub + Div + Mul+ Mul + PartialOrd+PartialEq, 90 | { 91 | if x<(x*-1){ 92 | return x*-1; 93 | } 94 | x 95 | } 96 | ///returns the absolute value of the number f number 97 | /// 98 | ///``` 99 | ///use metropolis::math::*; 100 | ///assert_eq!(absf(-1.5),1.5); 101 | ///``` 102 | pub fn absf(x: T) -> T 103 | where 104 | T: Copy + Clone + Add + Sub + Div + Mul+ Mul + PartialOrd+PartialEq, 105 | { 106 | if x<(x*-1.0){ 107 | return x*-1.0; 108 | } 109 | x 110 | }*/ 111 | ///converts from one range to another 112 | /// 113 | ///``` 114 | ///use metropolis::math::*; 115 | ///assert_eq!(map(1.0,0.0,2.0,0.0,1.0),0.5); 116 | ///``` 117 | pub fn map(x: T, a1: T, a2: T, b1: T, b2: T) -> f64 118 | where 119 | T: Copy + Clone + Add + Sub + Div + Mul + Sub + Add, 120 | { 121 | b1 + ((x - a1) / (a2 - a1) * (b2 - b1)) 122 | } 123 | #[allow(clippy::approx_constant)] 124 | pub const PI: f32 = 3.14159265359; 125 | pub const TWO_PI: f32 = PI * 2.0; 126 | ///create evenly spaced points inside the space between two points: 127 | ///``` 128 | ///use metropolis::math::*; 129 | ///assert_eq!(linspace(0.0,1.0,4),vec![0.0,0.25,0.5,0.75,1.0]); 130 | ///``` 131 | pub fn linspace(start: f64, finish: f64, n: u64) -> Vec { 132 | let mut vec1 = vec![]; 133 | for i in 0..(n + 1) { 134 | vec1.push(((finish - start) / n as f64) * i as f64 + start); 135 | } 136 | vec1 137 | } 138 | ///takes 8 values(4 x's and 4 y's ad constructs a 100 points array of a catmull rom chain curve 139 | ///from them using he algorithm. 140 | pub fn catmull_rom_chain( 141 | x1: i64, 142 | y1: i64, 143 | x2: i64, 144 | y2: i64, 145 | x3: i64, 146 | y3: i64, 147 | x4: i64, 148 | y4: i64, 149 | ) -> [[f64; 2]; 100] { 150 | let t0 = 0f64; 151 | let t1 = (((x2 - x1).pow(2) + (y2 - y1).pow(2)) as f64).sqrt().sqrt() + t0 as f64; 152 | let t2 = (((x3 - x2).pow(2) + (y3 - y2).pow(2)) as f64).sqrt().sqrt() + t1 as f64; 153 | let t3 = (((x4 - x3).pow(2) + (y4 - y3).pow(2)) as f64).sqrt().sqrt() + t2 as f64; 154 | let t = linspace_in(t1, t2); 155 | let tt = Vector{vec:linspace_in(t1, t2).to_vec()}; 156 | let ttt = [((tt.clone()*-1.0+t1)/(t1+t0)*(x1 as f64))+((tt.clone()-t0)/(t1-t0)*(x2 as f64)),(tt.clone()*-1.0+t1)/(t1+t0)*(y1 as f64)+((tt.clone()-t0)/(t1-t0)*(y2 as f64))]; 157 | let ttt2 = [((tt.clone()*-1.0+t2)/(t2+t1)*(x2 as f64))+((tt.clone()-t1)/(t2-t1)*(x3 as f64)),(tt.clone()*-1.0+t2)/(t2+t1)*(y2 as f64)+((tt.clone()-t1)/(t2-t1)*(y3 as f64))]; 158 | let ttt3 = [((tt.clone()*-1.0+t3)/(t3+t2)*(x3 as f64))+((tt.clone()-t2)/(t3-t2)*(x4 as f64)),(tt.clone()*-1.0+t3)/(t3+t2)*(y3 as f64)+((tt.clone()-t2)/(t3-t2)*(y4 as f64))]; 159 | println!("{:?}",ttt); 160 | let a11 = [ 161 | compute_ops( 162 | compute_ops( 163 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t1, ops::FloatAdd), 164 | t1 - t0, 165 | ops::FloatDiv, 166 | ), 167 | x1 as f64, 168 | ops::FloatMult, 169 | ), 170 | compute_ops( 171 | compute_ops( 172 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t1, ops::FloatAdd), 173 | t1 - t0, 174 | ops::FloatDiv, 175 | ), 176 | y1 as f64, 177 | ops::FloatMult, 178 | ), 179 | ]; 180 | let a12 = [ 181 | compute_ops( 182 | compute_ops(compute_ops(t, t0, ops::FloatSub), t1 - t0, ops::FloatDiv), 183 | x2 as f64, 184 | ops::FloatMult, 185 | ), 186 | compute_ops( 187 | compute_ops(compute_ops(t, t0, ops::FloatAdd), t1 - t0, ops::FloatDiv), 188 | y2 as f64, 189 | ops::FloatMult, 190 | ), 191 | ]; 192 | let a1 = [ 193 | compute_ops2(a11[0], a12[0], ops::FloatAddVecs), 194 | compute_ops2(a11[1], a12[1], ops::FloatAddVecs), 195 | ]; 196 | let a21 = [ 197 | compute_ops( 198 | compute_ops( 199 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t2, ops::FloatAdd), 200 | t2 - t1, 201 | ops::FloatDiv, 202 | ), 203 | x2 as f64, 204 | ops::FloatMult, 205 | ), 206 | compute_ops( 207 | compute_ops( 208 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t2, ops::FloatAdd), 209 | t2 - t1, 210 | ops::FloatDiv, 211 | ), 212 | y2 as f64, 213 | ops::FloatMult, 214 | ), 215 | ]; 216 | let a22 = [ 217 | compute_ops( 218 | compute_ops(compute_ops(t, t1, ops::FloatSub), t2 - t1, ops::FloatDiv), 219 | x3 as f64, 220 | ops::FloatMult, 221 | ), 222 | compute_ops( 223 | compute_ops(compute_ops(t, t1, ops::FloatAdd), t2 - t1, ops::FloatDiv), 224 | y3 as f64, 225 | ops::FloatMult, 226 | ), 227 | ]; 228 | let a2 = [ 229 | compute_ops2(a21[0], a22[0], ops::FloatAddVecs), 230 | compute_ops2(a21[1], a22[1], ops::FloatAddVecs), 231 | ]; 232 | let a31 = [ 233 | compute_ops( 234 | compute_ops( 235 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t3, ops::FloatAdd), 236 | t3 - t2, 237 | ops::FloatDiv, 238 | ), 239 | x3 as f64, 240 | ops::FloatMult, 241 | ), 242 | compute_ops( 243 | compute_ops( 244 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t3, ops::FloatAdd), 245 | t3 - t2, 246 | ops::FloatDiv, 247 | ), 248 | y3 as f64, 249 | ops::FloatMult, 250 | ), 251 | ]; 252 | let a32 = [ 253 | compute_ops( 254 | compute_ops(compute_ops(t, t2, ops::FloatSub), t3 - t2, ops::FloatDiv), 255 | x4 as f64, 256 | ops::FloatMult, 257 | ), 258 | compute_ops( 259 | compute_ops(compute_ops(t, t2, ops::FloatAdd), t3 - t2, ops::FloatDiv), 260 | y4 as f64, 261 | ops::FloatMult, 262 | ), 263 | ]; 264 | let a3 = [ 265 | compute_ops2(a31[0], a32[0], ops::FloatAddVecs), 266 | compute_ops2(a31[1], a32[1], ops::FloatAddVecs), 267 | ]; 268 | let b11 = [ 269 | compute_ops2( 270 | compute_ops( 271 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t2, ops::FloatAdd), 272 | t2 - t0, 273 | ops::FloatDiv, 274 | ), 275 | a1[0], 276 | ops::FloatMultVecs, 277 | ), 278 | compute_ops2( 279 | compute_ops( 280 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t2, ops::FloatAdd), 281 | t2 - t0, 282 | ops::FloatDiv, 283 | ), 284 | a1[1], 285 | ops::FloatMultVecs, 286 | ), 287 | ]; 288 | let b12 = [ 289 | compute_ops2( 290 | compute_ops(compute_ops(t, t0, ops::FloatSub), t2 - t0, ops::FloatDiv), 291 | a2[0], 292 | ops::FloatMultVecs, 293 | ), 294 | compute_ops2( 295 | compute_ops(compute_ops(t, t2, ops::FloatAdd), t2 - t0, ops::FloatDiv), 296 | a2[1], 297 | ops::FloatMultVecs, 298 | ), 299 | ]; 300 | let b1 = [ 301 | compute_ops2(b11[0], b12[0], ops::FloatAddVecs), 302 | compute_ops2(b11[1], b12[1], ops::FloatAddVecs), 303 | ]; 304 | let b21 = [ 305 | compute_ops2( 306 | compute_ops( 307 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t3, ops::FloatAdd), 308 | t3 - t1, 309 | ops::FloatDiv, 310 | ), 311 | a2[0], 312 | ops::FloatMultVecs, 313 | ), 314 | compute_ops2( 315 | compute_ops( 316 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t3, ops::FloatAdd), 317 | t3 - t1, 318 | ops::FloatDiv, 319 | ), 320 | a2[1], 321 | ops::FloatMultVecs, 322 | ), 323 | ]; 324 | let b22 = [ 325 | compute_ops2( 326 | compute_ops(compute_ops(t, t1, ops::FloatSub), t3 - t1, ops::FloatDiv), 327 | a3[0], 328 | ops::FloatMultVecs, 329 | ), 330 | compute_ops2( 331 | compute_ops(compute_ops(t, t1, ops::FloatAdd), t3 - t1, ops::FloatDiv), 332 | a3[1], 333 | ops::FloatMultVecs, 334 | ), 335 | ]; 336 | let b2 = [ 337 | compute_ops2(b21[0], b22[0], ops::FloatAddVecs), 338 | compute_ops2(b21[1], b22[1], ops::FloatAddVecs), 339 | ]; 340 | 341 | let c11 = [ 342 | compute_ops2( 343 | compute_ops( 344 | compute_ops(compute_ops(t, -1.0, ops::FloatMult), t2, ops::FloatAdd), 345 | t2 - t1, 346 | ops::FloatDiv, 347 | ), 348 | b1[0], 349 | ops::FloatMultVecs, 350 | ), 351 | compute_ops2( 352 | compute_ops( 353 | compute_ops(compute_ops(t, -1f64, ops::FloatMult), t2, ops::FloatAdd), 354 | t2 - t1, 355 | ops::FloatDiv, 356 | ), 357 | b1[1], 358 | ops::FloatMultVecs, 359 | ), 360 | ]; 361 | let c12 = [ 362 | compute_ops2( 363 | compute_ops(compute_ops(t, t1, ops::FloatSub), t2 - t1, ops::FloatDiv), 364 | b2[0], 365 | ops::FloatMultVecs, 366 | ), 367 | compute_ops2( 368 | compute_ops(compute_ops(t, t1, ops::FloatAdd), t2 - t1, ops::FloatDiv), 369 | b2[1], 370 | ops::FloatMultVecs, 371 | ), 372 | ]; 373 | let c1 = [ 374 | compute_ops2(c11[0], c12[0], ops::FloatAddVecs), 375 | compute_ops2(c11[1], c12[1], ops::FloatAddVecs), 376 | ]; 377 | let mut c: [[f64; 2]; 100] = [[0f64; 2]; 100]; 378 | for i in 0..99 { 379 | c[i] = [c1[0][i], c1[1][i]]; 380 | } 381 | c 382 | } 383 | fn linspace_in(start: f64, finish: f64) -> [f64; 100] { 384 | let mut arr1: [f64; 100] = [0.0; 100]; 385 | for i in 0..(99) { 386 | arr1[i] = ((finish - start) / 100 as f64) * i as f64 + start; 387 | } 388 | arr1 389 | } 390 | pub fn bezier_points( 391 | x1: i64, 392 | y1: i64, 393 | x2: i64, 394 | y2: i64, 395 | x3: i64, 396 | y3: i64, 397 | x4: i64, 398 | y4: i64, 399 | ) -> [[f64; 2]; 101] { 400 | let mut t: f64; 401 | let mut b: [f64; 2]; 402 | let mut arr_b = [[0f64; 2]; 101]; 403 | for i in 0..101 { 404 | t = i as f64 / 100.0; 405 | b = [ 406 | ((1.0 - t).powf(3.0) * x1 as f64) 407 | + (3.0 * (1.0 - t).powf(2.0) * t) * x2 as f64 408 | + (3.0 * (1.0 - t) * t.powf(2.0)) * x3 as f64 409 | + (t.powf(3.0)) * x4 as f64, 410 | ((1.0 - t).powf(3.0) * y1 as f64) 411 | + (3.0 * (1.0 - t).powf(2.0) * t) * y2 as f64 412 | + (3.0 * (1.0 - t) * t.powf(2.0)) * y3 as f64 413 | + (t.powf(3.0)) * y4 as f64, 414 | ]; 415 | arr_b[i] = b; 416 | } 417 | arr_b 418 | } 419 | -------------------------------------------------------------------------------- /src/page.rs: -------------------------------------------------------------------------------- 1 | use crate::elements::PageElements; 2 | use crate::canvas::Canvas; 3 | use crate::mapping; 4 | use vulkano::image::Dimensions; 5 | //use winit::MouseScrollDelta; 6 | use winit::{ModifiersState/*,KeyboardInput,ElementState,Event, WindowEvent*/,VirtualKeyCode}; 7 | pub use winit::MouseButton; 8 | use crate::color::Color; 9 | #[derive(Copy,Clone,PartialEq)] 10 | struct MouseScroll{ 11 | pub delta:(i64,i64), 12 | pub moder:ModifiersState, 13 | } 14 | impl MouseScroll{ 15 | pub fn new()->MouseScroll{ 16 | let moder = ModifiersState{shift:false,ctrl:false,alt:false,logo:false}; 17 | let delta = (0,0); 18 | MouseScroll{delta,moder} 19 | } 20 | pub fn delta_x(self)->i64{ 21 | self.delta.0 22 | } 23 | pub fn delta_y(self)->i64{ 24 | self.delta.1//.PixelDelta.y as i64 25 | } 26 | } 27 | #[derive(Copy,Clone,PartialEq)] 28 | struct Mouse{ 29 | pub btn:Option, 30 | pub moder:ModifiersState, 31 | } 32 | impl Mouse{ 33 | pub fn new()->Mouse{ 34 | let moder = ModifiersState{shift:false,ctrl:false,alt:false,logo:false}; 35 | let btn = None; 36 | Mouse{btn,moder} 37 | } 38 | } 39 | #[derive(Copy,Clone,PartialEq)] 40 | struct Key{ 41 | pub keycode:Option, 42 | pub moder:ModifiersState, 43 | pub keep_key: bool, 44 | } 45 | impl Key{ 46 | pub fn new()->Key{ 47 | let moder = ModifiersState{shift:false,ctrl:false,alt:false,logo:false}; 48 | let keycode = None; 49 | Key{keycode,moder,keep_key:false} 50 | } 51 | pub fn get_mod(self)->ModifiersState{ 52 | self.moder 53 | } 54 | } 55 | #[derive(Clone)] 56 | struct Page{ 57 | size: (u16, u16), 58 | background: [f32; 4], 59 | texture:Option<(Vec,Dimensions)>, 60 | elements:Vec, 61 | canvases:Vec, 62 | key:Key, 63 | cursor_pos:(u16,u16), 64 | mouse:Mouse, 65 | mouse_scroll:MouseScroll, 66 | } 67 | impl Page{ 68 | ///returns the current key that is pressed on the mouse. 69 | #[allow(non_snake_case)] 70 | pub fn mouseClick(&mut self)->MouseButton{ 71 | match self.mouse.btn{ 72 | Some(btn)=> {return btn;}, 73 | None=> {return MouseButton::Other(99);} 74 | } 75 | } 76 | ///returns the current key that is pressed. 77 | #[allow(non_snake_case)] 78 | pub fn keyPressed(&mut self)->VirtualKeyCode{ 79 | match self.key.keycode{ 80 | Some(key)=> {return key;}, 81 | None=> {return VirtualKeyCode::Power;} 82 | } 83 | } 84 | ///keeps the key pressed in the key event until a new key is pressed 85 | #[allow(non_snake_case)] 86 | pub fn lockKeyEvent(&mut self){ 87 | self.key.keep_key = true; 88 | } 89 | ///returns the x scroll delta of the mouse 90 | #[allow(non_snake_case)] 91 | pub fn mouseScrollX(&self)->i64{ 92 | self.mouse_scroll.delta_x() 93 | } 94 | ///returns the y scroll delta of the mouse 95 | #[allow(non_snake_case)] 96 | pub fn mouseScrollY(&self)->i64{ 97 | self.mouse_scroll.delta_y() 98 | } 99 | ///returns the x position of the mouse 100 | #[allow(non_snake_case)] 101 | pub fn mouseX(&self)->u16{ 102 | self.cursor_pos.0 103 | } 104 | ///returns the y position of the mouse 105 | #[allow(non_snake_case)] 106 | pub fn mouseY(&self)->u16{ 107 | self.cursor_pos.1 108 | } 109 | ///returns the current state of the modifiers 110 | pub fn get_modifiers(self)->ModifiersState{ 111 | self.key.get_mod() 112 | } 113 | ///sets the background color(using the color struct). 114 | pub fn background(&mut self,color:Color){ 115 | let r = color.get_r(); 116 | let g = color.get_g(); 117 | let b = color.get_b(); 118 | let a = color.get_a(); 119 | self.background = mapping::map_colors([r, g, b, a]); 120 | } 121 | ///creates a new page 122 | pub fn new(width:u16,height:u16)->Page{ 123 | Page{ 124 | size: (width, height), 125 | background:[0.0,0.0,0.0,1.0], 126 | texture:None, 127 | elements:vec![], 128 | canvases:vec![], 129 | key:Key::new(), 130 | cursor_pos:(0,0), 131 | mouse:Mouse::new(), 132 | mouse_scroll:MouseScroll::new(), 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/setup.rs: -------------------------------------------------------------------------------- 1 | use crate::shaders::*; 2 | use crate::vertex::Vertex; 3 | use std::sync::Arc; 4 | use vulkano::command_buffer::DynamicState; 5 | use vulkano::device::{Device, DeviceExtensions, Queue}; 6 | use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract, Subpass}; 7 | use vulkano::image::SwapchainImage; 8 | use vulkano::instance::{Instance, PhysicalDevice}; 9 | use vulkano::pipeline::viewport::Viewport; 10 | use vulkano::pipeline::GraphicsPipeline; 11 | use vulkano::pipeline::GraphicsPipelineAbstract; 12 | use vulkano::swapchain::*; 13 | use vulkano::swapchain::{PresentMode, SurfaceTransform, Swapchain}; 14 | use vulkano::sync; 15 | use vulkano::sync::GpuFuture; 16 | use vulkano_win::VkSurfaceBuild; 17 | use winit::dpi::LogicalSize; 18 | use winit::EventsLoop; 19 | use winit::{Window, WindowBuilder}; 20 | pub struct Preper { 21 | pub device: Arc, 22 | pub queue: Arc, 23 | pub surface: Arc>, 24 | pub swapchain: Arc>, 25 | pub images: Vec>>, 26 | pub render_pass: Arc, 27 | pub fill_pipeline: Arc, 28 | pub tex_pipeline: Arc, 29 | pub stroke_pipeline: Arc, 30 | pub dynamic_state: DynamicState, 31 | pub framebuffers: Vec>, 32 | pub recreate_swapchain: bool, 33 | pub previous_frame_end: Option>, 34 | } 35 | pub fn init(w: u16, h: u16) -> (Preper, EventsLoop) { 36 | let instance = { 37 | let extensions = vulkano_win::required_extensions(); 38 | Instance::new(None, &extensions, None).unwrap() 39 | }; 40 | let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); 41 | let events_loop = EventsLoop::new(); 42 | let surface = WindowBuilder::new() 43 | .with_dimensions(LogicalSize { 44 | width: w as f64, 45 | height: h as f64, 46 | }) 47 | .with_title("Canvas") 48 | .with_decorations(true) 49 | .build_vk_surface(&events_loop, instance.clone()) 50 | .unwrap(); 51 | let window = surface.window(); 52 | let queue_family = physical 53 | .queue_families() 54 | .find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false)) 55 | .unwrap(); 56 | let device_ext = DeviceExtensions { 57 | khr_swapchain: true, 58 | ..DeviceExtensions::none() 59 | }; 60 | let (device, mut queues) = Device::new( 61 | physical, 62 | physical.supported_features(), 63 | &device_ext, 64 | [(queue_family, 0.5)].iter().cloned(), 65 | ) 66 | .unwrap(); 67 | let queue = queues.next().unwrap(); 68 | let (swapchain, images) = { 69 | let caps = surface.capabilities(physical).unwrap(); 70 | let usage = caps.supported_usage_flags; 71 | let alpha = caps.supported_composite_alpha.iter().next().unwrap(); 72 | let format = caps.supported_formats[0].0; 73 | let initial_dimensions = { 74 | // convert to physical pixels 75 | let dimensions: (u32, u32) = window 76 | .get_inner_size() 77 | .unwrap() 78 | .to_physical(window.get_hidpi_factor()) 79 | .into(); 80 | [dimensions.0, dimensions.1] 81 | }; 82 | Swapchain::new( 83 | device.clone(), 84 | surface.clone(), 85 | caps.min_image_count, 86 | format, 87 | initial_dimensions, 88 | 1, 89 | usage, 90 | &queue, 91 | SurfaceTransform::Identity, 92 | alpha, 93 | PresentMode::Fifo, 94 | true, 95 | None, 96 | ) 97 | .unwrap() 98 | }; 99 | let render_pass = Arc::new( 100 | vulkano::single_pass_renderpass!( 101 | device.clone(), 102 | attachments: { 103 | color: { 104 | load:Clear, 105 | store: Store, 106 | format: swapchain.format(), 107 | samples: 1, 108 | } 109 | }, 110 | pass: { 111 | color: [color], 112 | depth_stencil: {} 113 | } 114 | ) 115 | .unwrap(), 116 | ); 117 | let vs = vs::Shader::load(device.clone()).unwrap(); 118 | let fs = fs::Shader::load(device.clone()).unwrap(); 119 | let fsimg = fsimg::Shader::load(device.clone()).unwrap(); 120 | let fill_pipeline = Arc::new( 121 | GraphicsPipeline::start() 122 | .vertex_input_single_buffer::() 123 | .vertex_shader(vs.main_entry_point(), ()) 124 | .triangle_list() 125 | .line_width_dynamic() 126 | .viewports_dynamic_scissors_irrelevant(1) 127 | .fragment_shader(fs.main_entry_point(), ()) 128 | .blend_alpha_blending() 129 | .render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) 130 | .build(device.clone()) 131 | .unwrap(), 132 | ); 133 | let tex_pipeline = Arc::new( 134 | GraphicsPipeline::start() 135 | .vertex_input_single_buffer::() 136 | .vertex_shader(vs.main_entry_point(), ()) 137 | .triangle_list() 138 | .line_width_dynamic() 139 | .viewports_dynamic_scissors_irrelevant(1) 140 | .fragment_shader(fsimg.main_entry_point(), ()) 141 | .blend_alpha_blending() 142 | .render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) 143 | .build(device.clone()) 144 | .unwrap(), 145 | ); 146 | let stroke_pipeline = Arc::new( 147 | GraphicsPipeline::start() 148 | .vertex_input_single_buffer::() 149 | .vertex_shader(vs.main_entry_point(), ()) 150 | .line_list() 151 | .line_width_dynamic() 152 | .viewports_dynamic_scissors_irrelevant(1) 153 | .fragment_shader(fs.main_entry_point(), ()) 154 | .render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) 155 | .build(device.clone()) 156 | .unwrap(), 157 | ); 158 | let mut dynamic_state = DynamicState { 159 | line_width: None, 160 | viewports: None, 161 | scissors: None, 162 | compare_mask: None, 163 | write_mask: None, 164 | reference: None, 165 | }; 166 | let framebuffers = 167 | window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state); 168 | let recreate_swapchain = false; 169 | let previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box); 170 | ( 171 | Preper { 172 | device, 173 | queue, 174 | surface, 175 | swapchain, 176 | images, 177 | render_pass, 178 | fill_pipeline, 179 | tex_pipeline, 180 | stroke_pipeline, 181 | dynamic_state, 182 | framebuffers, 183 | recreate_swapchain, 184 | previous_frame_end, 185 | }, 186 | events_loop, 187 | ) 188 | } 189 | pub fn window_size_dependent_setup( 190 | images: &[Arc>], 191 | render_pass: Arc, 192 | dynamic_state: &mut DynamicState, 193 | ) -> Vec> { 194 | let dimensions = images[0].dimensions(); 195 | 196 | let viewport = Viewport { 197 | origin: [0.0, 0.0], 198 | dimensions: [dimensions[0] as f32, dimensions[1] as f32], 199 | depth_range: 0.0..1.0, 200 | }; 201 | dynamic_state.viewports = Some(vec![viewport]); 202 | 203 | images 204 | .iter() 205 | .map(|image| { 206 | Arc::new( 207 | Framebuffer::start(render_pass.clone()) 208 | .add(image.clone()) 209 | .unwrap() 210 | .build() 211 | .unwrap(), 212 | ) as Arc 213 | }) 214 | .collect::>() 215 | } 216 | -------------------------------------------------------------------------------- /src/shaders.rs: -------------------------------------------------------------------------------- 1 | pub mod vs { 2 | vulkano_shaders::shader! { 3 | ty: "vertex", 4 | src: "#version 450 5 | precision highp float; 6 | layout(location = 0) in vec2 position; 7 | layout(location = 1) in vec4 color; 8 | layout(location = 2) in vec2 tex_coords; 9 | layout(location = 0) out vec4 _color; 10 | layout(location = 1) out vec2 _tex_coords; 11 | void main() { 12 | gl_Position = vec4(position, 0.0, 1.0); 13 | _color = color; 14 | _tex_coords = tex_coords;//position+vec2(tex_coords*2);//position+ vec2(tex_coords*2); 15 | }" 16 | } 17 | } 18 | pub mod fs { 19 | vulkano_shaders::shader! { 20 | ty: "fragment", 21 | src: "#version 450 22 | precision highp float; 23 | layout(location = 0) in vec4 _color; 24 | layout(location = 1) in vec2 _tex_coords; 25 | layout(location = 0) out vec4 f_color; 26 | void main() { 27 | f_color = _color; 28 | } 29 | " 30 | } 31 | } 32 | pub mod fsimg { 33 | vulkano_shaders::shader! { 34 | ty: "fragment", 35 | src: "#version 450 36 | precision highp float; 37 | layout(location = 0) in vec4 _color; 38 | layout(location = 1) in vec2 _tex_coords; 39 | layout(location = 0) out vec4 f_color; 40 | layout(set = 0, binding = 0) uniform sampler2D tex; 41 | void main() { 42 | f_color = texture(tex, _tex_coords); 43 | //f_color = _color; 44 | } 45 | " 46 | } 47 | } 48 | pub mod cs_sub { 49 | vulkano_shaders::shader! { 50 | ty: "compute", 51 | src: "#version 450 52 | precision highp float; 53 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 54 | layout(set = 0, binding = 0) buffer Data { 55 | int vecer[]; 56 | } buf; 57 | layout(set = 0, binding = 1) buffer Data2 { 58 | int sclr; 59 | } buf2; 60 | void main(){ 61 | int idx = int(gl_GlobalInvocationID.x); 62 | buf.vecer[idx]-=buf2.sclr; 63 | }" 64 | } 65 | } 66 | pub mod cs_add { 67 | vulkano_shaders::shader! { 68 | ty: "compute", 69 | src: "#version 450 70 | precision highp float; 71 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 72 | layout(set = 0, binding = 0) buffer Data { 73 | int vecer[]; 74 | } buf; 75 | layout(set = 0, binding = 1) buffer Data2 { 76 | int sclr; 77 | } buf2; 78 | void main(){ 79 | int idx = int(gl_GlobalInvocationID.x); 80 | buf.vecer[idx]+=buf2.sclr; 81 | }" 82 | } 83 | } 84 | pub mod cs_mult { 85 | vulkano_shaders::shader! { 86 | ty: "compute", 87 | src: "#version 450 88 | precision highp float; 89 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 90 | layout(set = 0, binding = 0) buffer Data { 91 | int vecer[]; 92 | } buf; 93 | layout(set = 0, binding = 1) buffer Data2 { 94 | int sclr; 95 | } buf2; 96 | void main(){ 97 | int idx = int(gl_GlobalInvocationID.x); 98 | buf.vecer[idx]*=buf2.sclr; 99 | }" 100 | } 101 | } 102 | pub mod cs_div { 103 | vulkano_shaders::shader! { 104 | ty: "compute", 105 | src: "#version 450 106 | precision highp float; 107 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 108 | layout(set = 0, binding = 0) buffer Data { 109 | int vecer[]; 110 | } buf; 111 | layout(set = 0, binding = 1) buffer Data2 { 112 | int sclr; 113 | } buf2; 114 | void main(){ 115 | int idx = int(gl_GlobalInvocationID.x); 116 | buf.vecer[idx]/=buf2.sclr; 117 | }" 118 | } 119 | } 120 | pub mod cs_float_div { 121 | vulkano_shaders::shader! { 122 | ty: "compute", 123 | src: "#version 450 124 | precision highp float; 125 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 126 | layout(set = 0, binding = 0) buffer Data { 127 | float vecer[]; 128 | } buf; 129 | layout(set = 0, binding = 1) buffer Data2 { 130 | float sclr; 131 | } buf2; 132 | void main(){ 133 | int idx = int(gl_GlobalInvocationID.x); 134 | buf.vecer[idx]/=buf2.sclr; 135 | }" 136 | } 137 | } 138 | pub mod cs_float_sub { 139 | vulkano_shaders::shader! { 140 | ty: "compute", 141 | src: "#version 450 142 | precision highp float; 143 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 144 | layout(set = 0, binding = 0) buffer Data { 145 | float vecer[]; 146 | } buf; 147 | layout(set = 0, binding = 1) buffer Data2 { 148 | float sclr; 149 | } buf2; 150 | void main(){ 151 | int idx = int(gl_GlobalInvocationID.x); 152 | buf.vecer[idx]-=buf2.sclr; 153 | }" 154 | } 155 | } 156 | pub mod cs_float_add { 157 | vulkano_shaders::shader! { 158 | ty: "compute", 159 | src: "#version 450 160 | precision highp float; 161 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 162 | layout(set = 0, binding = 0) buffer Data { 163 | float vecer[]; 164 | } buf; 165 | layout(set = 0, binding = 1) buffer Data2 { 166 | float sclr; 167 | } buf2; 168 | void main(){ 169 | int idx = int(gl_GlobalInvocationID.x); 170 | buf.vecer[idx]+=buf2.sclr; 171 | }" 172 | } 173 | } 174 | pub mod cs_float_mult { 175 | vulkano_shaders::shader! { 176 | ty: "compute", 177 | src: "#version 450 178 | precision highp float; 179 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 180 | layout(set = 0, binding = 0) buffer Data { 181 | float vecer[]; 182 | } buf; 183 | layout(set = 0, binding = 1) buffer Data2 { 184 | float sclr; 185 | } buf2; 186 | void main(){ 187 | int idx = int(gl_GlobalInvocationID.x); 188 | buf.vecer[idx]*=buf2.sclr; 189 | }" 190 | } 191 | } 192 | pub mod cs_float_add_vec { 193 | vulkano_shaders::shader! { 194 | ty: "compute", 195 | src: "#version 450 196 | precision highp float; 197 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 198 | layout(set = 0, binding = 0) buffer Data { 199 | float vecer[]; 200 | } buf; 201 | layout(set = 0, binding = 1) buffer Data2 { 202 | float vecer[]; 203 | } buf2; 204 | void main(){ 205 | int idx = int(gl_GlobalInvocationID.x); 206 | buf.vecer[idx]+=buf2.vecer[idx]; 207 | }" 208 | } 209 | } 210 | pub mod cs_float_sub_vec { 211 | vulkano_shaders::shader! { 212 | ty: "compute", 213 | src: "#version 450 214 | precision highp float; 215 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 216 | layout(set = 0, binding = 0) buffer Data { 217 | float vecer[]; 218 | } buf; 219 | layout(set = 0, binding = 1) buffer Data2 { 220 | float vecer[]; 221 | } buf2; 222 | void main(){ 223 | int idx = int(gl_GlobalInvocationID.x); 224 | buf.vecer[idx]-=buf2.vecer[idx]; 225 | }" 226 | } 227 | } 228 | pub mod cs_add_vec { 229 | vulkano_shaders::shader! { 230 | ty: "compute", 231 | src: "#version 450 232 | precision highp float; 233 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 234 | layout(set = 0, binding = 0) buffer Data { 235 | int vecer[]; 236 | } buf; 237 | layout(set = 0, binding = 1) buffer Data2 { 238 | int vecer[]; 239 | } buf2; 240 | void main(){ 241 | int idx = int(gl_GlobalInvocationID.x); 242 | buf.vecer[idx]+=buf2.vecer[idx]; 243 | }" 244 | } 245 | } 246 | pub mod cs_sub_vec { 247 | vulkano_shaders::shader! { 248 | ty: "compute", 249 | src: "#version 450 250 | precision highp float; 251 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 252 | layout(set = 0, binding = 0) buffer Data { 253 | int vecer[]; 254 | } buf; 255 | layout(set = 0, binding = 1) buffer Data2 { 256 | int vecer[]; 257 | } buf2; 258 | void main(){ 259 | int idx = int(gl_GlobalInvocationID.x); 260 | buf.vecer[idx]-=buf2.vecer[idx]; 261 | }" 262 | } 263 | } 264 | pub mod cs_float_div_vec { 265 | vulkano_shaders::shader! { 266 | ty: "compute", 267 | src: "#version 450 268 | precision highp float; 269 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 270 | layout(set = 0, binding = 0) buffer Data { 271 | float vecer[]; 272 | } buf; 273 | layout(set = 0, binding = 1) buffer Data2 { 274 | float vecer[]; 275 | } buf2; 276 | void main(){ 277 | int idx = int(gl_GlobalInvocationID.x); 278 | buf.vecer[idx]/=buf2.vecer[idx]; 279 | }" 280 | } 281 | } 282 | pub mod cs_float_mult_vec { 283 | vulkano_shaders::shader! { 284 | ty: "compute", 285 | src: "#version 450 286 | precision highp float; 287 | layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; 288 | layout(set = 0, binding = 0) buffer Data { 289 | float vecer[]; 290 | } buf; 291 | layout(set = 0, binding = 1) buffer Data2 { 292 | float vecer[]; 293 | } buf2; 294 | void main(){ 295 | int idx = int(gl_GlobalInvocationID.x); 296 | buf.vecer[idx]*=buf2.vecer[idx]; 297 | }" 298 | } 299 | } 300 | pub mod vstext { 301 | vulkano_shaders::shader!{ 302 | ty: "vertex", 303 | src:" 304 | #version 450 305 | 306 | layout(location = 0) in vec2 position; 307 | layout(location = 1) in vec2 tex_position; 308 | layout(location = 2) in vec4 color; 309 | layout(location = 0) out vec2 v_tex_position; 310 | layout(location = 1) out vec4 v_color; 311 | 312 | void main() { 313 | gl_Position = vec4(position, 0.0, 1.0); 314 | v_tex_position = tex_position; 315 | v_color = color; 316 | }" 317 | } 318 | } 319 | 320 | pub mod fstext { 321 | vulkano_shaders::shader!{ 322 | ty: "fragment", 323 | src:" 324 | #version 450 325 | 326 | layout(location = 0) in vec2 v_tex_position; 327 | layout(location = 1) in vec4 v_color; 328 | layout(location = 0) out vec4 f_color; 329 | 330 | layout(set = 0, binding = 0) uniform sampler2D tex; 331 | 332 | void main() { 333 | f_color = v_color * texture(tex, v_tex_position)[0]; 334 | }" 335 | } 336 | } 337 | 338 | -------------------------------------------------------------------------------- /src/text.rs: -------------------------------------------------------------------------------- 1 | use rusttype::{Font, PositionedGlyph, Scale, Rect, point}; 2 | use crate::fonts::*; 3 | use rusttype::gpu_cache::Cache; 4 | 5 | use vulkano::buffer::{CpuAccessibleBuffer, BufferUsage}; 6 | use vulkano::command_buffer::{DynamicState, AutoCommandBufferBuilder}; 7 | use vulkano::descriptor::descriptor_set::{PersistentDescriptorSet}; 8 | use vulkano::descriptor::pipeline_layout::PipelineLayoutAbstract; 9 | use vulkano::device::{Device, Queue}; 10 | use vulkano::format::{R8Unorm, ClearValue}; 11 | use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract}; 12 | use vulkano::image::{SwapchainImage, ImmutableImage, ImageUsage, ImageLayout, Dimensions}; 13 | use vulkano::pipeline::vertex::SingleBufferDefinition; 14 | use vulkano::pipeline::viewport::Viewport; 15 | use vulkano::pipeline::GraphicsPipeline; 16 | use vulkano::sampler::{Sampler, Filter, MipmapMode, SamplerAddressMode}; 17 | use vulkano::swapchain::Swapchain; 18 | 19 | use std::sync::Arc; 20 | 21 | #[derive(Default, Debug, Clone)] 22 | struct Vertex { 23 | position: [f32; 2], 24 | tex_position: [f32; 2], 25 | color: [f32; 4] 26 | } 27 | vulkano::impl_vertex!(Vertex, position, tex_position, color); 28 | 29 | mod vs { 30 | vulkano_shaders::shader!{ 31 | ty: "vertex", 32 | src:" 33 | #version 450 34 | 35 | layout(location = 0) in vec2 position; 36 | layout(location = 1) in vec2 tex_position; 37 | layout(location = 2) in vec4 color; 38 | layout(location = 0) out vec2 v_tex_position; 39 | layout(location = 1) out vec4 v_color; 40 | 41 | void main() { 42 | gl_Position = vec4(position, 0.0, 1.0); 43 | v_tex_position = tex_position; 44 | v_color = color; 45 | }" 46 | } 47 | } 48 | 49 | mod fs { 50 | vulkano_shaders::shader!{ 51 | ty: "fragment", 52 | src:" 53 | #version 450 54 | 55 | layout(location = 0) in vec2 v_tex_position; 56 | layout(location = 1) in vec4 v_color; 57 | layout(location = 0) out vec4 f_color; 58 | 59 | layout(set = 0, binding = 0) uniform sampler2D tex; 60 | 61 | void main() { 62 | f_color = v_color * texture(tex, v_tex_position)[0]; 63 | }" 64 | } 65 | } 66 | 67 | struct TextData { 68 | glyphs: Vec>, 69 | color: [f32; 4], 70 | } 71 | 72 | fn window_size_dependent_setup( 73 | images: &[Arc>], 74 | render_pass: Arc, 75 | dynamic_state: &mut DynamicState, 76 | ) -> Vec> where W: Send + Sync + 'static { 77 | let dimensions = images[0].dimensions(); 78 | 79 | let viewport = Viewport { 80 | origin: [0.0, 0.0], 81 | dimensions: [dimensions[0] as f32, dimensions[1] as f32], 82 | depth_range: 0.0..1.0, 83 | }; 84 | dynamic_state.viewports = Some(vec![viewport]); 85 | 86 | images 87 | .iter() 88 | .map(|image| { 89 | Arc::new( 90 | Framebuffer::start(render_pass.clone()) 91 | .add(image.clone()) 92 | .unwrap() 93 | .build() 94 | .unwrap(), 95 | ) as Arc 96 | }) 97 | .collect::>() 98 | } 99 | 100 | pub struct DrawText { 101 | device: Arc, 102 | queue: Arc, 103 | font: Font<'static>, 104 | cache: Cache<'static>, 105 | cache_pixel_buffer: Vec, 106 | pipeline: Arc, Box, Arc>>, 107 | framebuffers: Vec>, 108 | texts: Vec, 109 | buffer: Arc>, 110 | dynamic_state: DynamicState, 111 | } 112 | 113 | const CACHE_WIDTH: usize = 234; 114 | const CACHE_HEIGHT: usize = 234; 115 | 116 | impl DrawText { 117 | pub fn new(device: Arc, queue: Arc, swapchain: Arc>, images: &[Arc>], font:Fonts) -> DrawText where W: Send + Sync + 'static { 118 | //let mut font_file = File::open(font.get_ttf()).unwrap();//include_bytes!(font.get_ttf()); 119 | let font_data=font.get_ttf(); 120 | let font = Font::from_bytes(font_data as &[u8]).unwrap(); 121 | 122 | let vs = vs::Shader::load(device.clone()).unwrap(); 123 | let fs = fs::Shader::load(device.clone()).unwrap(); 124 | 125 | let cache = Cache::builder().dimensions(CACHE_WIDTH as u32, CACHE_HEIGHT as u32).build(); 126 | let cache_pixel_buffer = vec!(0; CACHE_WIDTH * CACHE_HEIGHT); 127 | 128 | let render_pass = Arc::new(vulkano::single_pass_renderpass!(device.clone(), 129 | attachments: { 130 | color: { 131 | load: Load, 132 | store: Store, 133 | format: swapchain.format(), 134 | samples: 1, 135 | } 136 | }, 137 | pass: { 138 | color: [color], 139 | depth_stencil: {} 140 | } 141 | ).unwrap()) as Arc; 142 | 143 | let mut dynamic_state = DynamicState { 144 | line_width: None, 145 | viewports: None, 146 | scissors: None, 147 | compare_mask: None, 148 | write_mask: None, 149 | reference: None, 150 | }; 151 | let framebuffers = 152 | window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state); 153 | /*let framebuffers = images.iter().map(|image| { 154 | Arc::new( 155 | Framebuffer::start(render_pass.clone()) 156 | .add(image.clone()).unwrap() 157 | .build().unwrap() 158 | ) as Arc 159 | }).collect::>(); 160 | let dims = [images[0].dimensions()[0] as f32,images[0].dimensions()[1] as f32];*/ 161 | let pipeline = Arc::new(GraphicsPipeline::start() 162 | .vertex_input_single_buffer() 163 | .vertex_shader(vs.main_entry_point(), ()) 164 | .triangle_list() 165 | .viewports_dynamic_scissors_irrelevant(1) 166 | .fragment_shader(fs.main_entry_point(), ()) 167 | .blend_alpha_blending() 168 | .render_pass(Subpass::from(render_pass.clone(), 0).unwrap()) 169 | .build(device.clone()) 170 | .unwrap() 171 | ); 172 | let buffer = CpuAccessibleBuffer::<[u8]>::from_iter( 173 | device.clone(), 174 | BufferUsage::all(), 175 | vec![].iter().cloned() 176 | ).unwrap(); 177 | DrawText { 178 | device: device.clone(), 179 | queue, 180 | font, 181 | cache, 182 | cache_pixel_buffer, 183 | pipeline, 184 | framebuffers, 185 | texts: vec!(), 186 | buffer, 187 | dynamic_state, 188 | } 189 | } 190 | 191 | pub fn queue_text(&mut self, x: f32, y: f32, size: f32, color: [f32; 4], text: &str) { 192 | let cache_pixel_buffer = &mut self.cache_pixel_buffer; 193 | let glyphs: Vec = self.font.layout(text, Scale::uniform(size), point(x, y)).map(|x| x.standalone()).collect(); 194 | for glyph in &glyphs { 195 | self.cache.queue_glyph(0, glyph.clone()); 196 | } 197 | self.texts.push(TextData { 198 | glyphs: glyphs.clone(), 199 | color: color, 200 | }); 201 | self.cache.cache_queued( 202 | |rect, src_data| { 203 | let width = (rect.max.x - rect.min.x) as usize; 204 | let height = (rect.max.y - rect.min.y) as usize; 205 | let mut dst_index = rect.min.y as usize * CACHE_WIDTH + rect.min.x as usize; 206 | let mut src_index = 0; 207 | 208 | for _ in 0..height { 209 | let dst_slice = &mut cache_pixel_buffer[dst_index..dst_index+width]; 210 | let src_slice = &src_data[src_index..src_index+width]; 211 | dst_slice.copy_from_slice(src_slice); 212 | 213 | dst_index += CACHE_WIDTH; 214 | src_index += width; 215 | } 216 | } 217 | ).unwrap(); 218 | let buffer = CpuAccessibleBuffer::<[u8]>::from_iter( 219 | self.device.clone(), 220 | BufferUsage::all(), 221 | self.cache_pixel_buffer.iter().cloned() 222 | ).unwrap(); 223 | self.buffer = buffer; 224 | } 225 | 226 | pub fn draw_text(&mut self, command_buffer: AutoCommandBufferBuilder, image_num: usize) -> AutoCommandBufferBuilder { 227 | let screen_width = self.framebuffers[image_num].dimensions()[0]; 228 | let screen_height = self.framebuffers[image_num].dimensions()[1]; 229 | //let cache_pixel_buffer = &mut self.cache_pixel_buffer; 230 | let cache = &mut self.cache; 231 | // update texture cache 232 | /*cache.cache_queued( 233 | |rect, src_data| { 234 | let width = (rect.max.x - rect.min.x) as usize; 235 | let height = (rect.max.y - rect.min.y) as usize; 236 | let mut dst_index = rect.min.y as usize * CACHE_WIDTH + rect.min.x as usize; 237 | let mut src_index = 0; 238 | 239 | for _ in 0..height { 240 | let dst_slice = &mut cache_pixel_buffer[dst_index..dst_index+width]; 241 | let src_slice = &src_data[src_index..src_index+width]; 242 | dst_slice.copy_from_slice(src_slice); 243 | 244 | dst_index += CACHE_WIDTH; 245 | src_index += width; 246 | } 247 | } 248 | ).unwrap();*/ 249 | //bad FPS start 250 | /*let buffer = CpuAccessibleBuffer::<[u8]>::from_iter( 251 | self.device.clone(), 252 | BufferUsage::all(), 253 | cache_pixel_buffer.iter().cloned() 254 | ).unwrap();*/ 255 | //let buffer = self.buffer; 256 | // bad FPS end 257 | let (cache_texture, cache_texture_write) = ImmutableImage::uninitialized( 258 | self.device.clone(), 259 | Dimensions::Dim2d { width: CACHE_WIDTH as u32, height: CACHE_HEIGHT as u32 }, 260 | R8Unorm, 261 | 1, 262 | ImageUsage { 263 | sampled: true, 264 | transfer_destination: true, 265 | .. ImageUsage::none() 266 | }, 267 | ImageLayout::General, 268 | Some(self.queue.family()) 269 | ).unwrap(); 270 | 271 | let sampler = Sampler::new( 272 | self.device.clone(), 273 | Filter::Linear, 274 | Filter::Linear, 275 | MipmapMode::Nearest, 276 | SamplerAddressMode::Repeat, 277 | SamplerAddressMode::Repeat, 278 | SamplerAddressMode::Repeat, 279 | 0.0, 1.0, 0.0, 0.0 280 | ).unwrap(); 281 | 282 | let set = Arc::new( 283 | PersistentDescriptorSet::start(self.pipeline.clone(), 0) 284 | .add_sampled_image(cache_texture.clone(), sampler).unwrap() 285 | .build().unwrap() 286 | ); 287 | 288 | let mut command_buffer = command_buffer 289 | .copy_buffer_to_image( 290 | self.buffer.clone(), 291 | cache_texture_write, 292 | ).unwrap() 293 | .begin_render_pass(self.framebuffers[image_num].clone(), false, vec![ClearValue::None]).unwrap(); 294 | 295 | // draw 296 | let mut vert1 = vec![]; 297 | for text in &mut self.texts.drain(..) { 298 | let vertices: Vec = text.glyphs.iter().flat_map(|g| { 299 | if let Ok(Some((uv_rect, screen_rect))) = cache.rect_for(0, g) { 300 | let gl_rect = Rect { 301 | min: point( 302 | (screen_rect.min.x as f32 / screen_width as f32 - 0.5) * 2.0, 303 | (screen_rect.min.y as f32 / screen_height as f32 - 0.5) * 2.0 304 | ), 305 | max: point( 306 | (screen_rect.max.x as f32 / screen_width as f32 - 0.5) * 2.0, 307 | (screen_rect.max.y as f32 / screen_height as f32 - 0.5) * 2.0 308 | ) 309 | }; 310 | vec!( 311 | Vertex { 312 | position: [gl_rect.min.x, gl_rect.max.y], 313 | tex_position: [uv_rect.min.x, uv_rect.max.y], 314 | color: text.color, 315 | }, 316 | Vertex { 317 | position: [gl_rect.min.x, gl_rect.min.y], 318 | tex_position: [uv_rect.min.x, uv_rect.min.y], 319 | color: text.color, 320 | }, 321 | Vertex { 322 | position: [gl_rect.max.x, gl_rect.min.y], 323 | tex_position: [uv_rect.max.x, uv_rect.min.y], 324 | color: text.color, 325 | }, 326 | 327 | Vertex { 328 | position: [gl_rect.max.x, gl_rect.min.y], 329 | tex_position: [uv_rect.max.x, uv_rect.min.y], 330 | color: text.color, 331 | }, 332 | Vertex { 333 | position: [gl_rect.max.x, gl_rect.max.y], 334 | tex_position: [uv_rect.max.x, uv_rect.max.y], 335 | color: text.color, 336 | }, 337 | Vertex { 338 | position: [gl_rect.min.x, gl_rect.max.y], 339 | tex_position: [uv_rect.min.x, uv_rect.max.y], 340 | color: text.color, 341 | }, 342 | ).into_iter() 343 | } 344 | else { 345 | vec!().into_iter() 346 | } 347 | }).collect(); 348 | for i in vertices{ 349 | vert1.push(i); 350 | } 351 | } 352 | 353 | let vertex_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::all(), vert1.into_iter()).unwrap(); 354 | command_buffer = command_buffer.draw(self.pipeline.clone(), &self.dynamic_state, vertex_buffer.clone(), set.clone(), ()).unwrap(); 355 | 356 | command_buffer.end_render_pass().unwrap() 357 | } 358 | } 359 | 360 | impl DrawTextTrait for AutoCommandBufferBuilder { 361 | fn draw_text(self, data: &mut DrawText, image_num: usize) -> AutoCommandBufferBuilder { 362 | data.draw_text(self, image_num) 363 | } 364 | } 365 | 366 | pub trait DrawTextTrait { 367 | fn draw_text(self, data: &mut DrawText, image_num: usize) -> AutoCommandBufferBuilder; 368 | } 369 | -------------------------------------------------------------------------------- /src/vector.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Mul; 2 | use std::ops::Div; 3 | use std::ops::Add; 4 | use std::ops::Sub; 5 | use std::ops::AddAssign; 6 | use std::ops::MulAssign; 7 | use std::ops::SubAssign; 8 | use std::ops::DivAssign; 9 | use std::fmt; 10 | use std::fmt::Display; 11 | #[derive(Clone,Debug)] 12 | pub struct Vector{ 13 | pub vec:Vec, 14 | } 15 | impl> Vector{ 16 | pub fn dot(self,vec1:Vector)->Option{ 17 | let mut x=0f32; 18 | if self.vec.len()!=vec1.vec.len(){ 19 | return None; 20 | } 21 | for v in 0..self.vec.len(){ 22 | x+=self.vec[v]*vec1.vec[v]; 23 | } 24 | Some(x) 25 | } 26 | } 27 | impl> Mul for Vector{ 28 | type Output = Self; 29 | fn mul(self,mul1:T)->Self{ 30 | let mut vec1 = Vector{vec:vec![]}; 31 | for t in self.vec{ 32 | vec1.vec.push(t *mul1); 33 | } 34 | vec1 35 | } 36 | } 37 | impl> Add> for Vector{ 38 | type Output = Self; 39 | fn add(self,add1:Vector)->Self{ 40 | let mut vec1 = Vector{vec:vec![]}; 41 | let mut c = 0; 42 | for t in self.vec{ 43 | vec1.vec.push(t +add1.vec[c]); 44 | c+=1; 45 | } 46 | vec1 47 | } 48 | } 49 | impl> Add for Vector{ 50 | type Output = Self; 51 | fn add(self,add1:T)->Self{ 52 | let mut vec1 = Vector{vec:vec![]}; 53 | for t in self.vec{ 54 | vec1.vec.push(t +add1); 55 | } 56 | vec1 57 | } 58 | } 59 | impl> Sub for Vector{ 60 | type Output = Self; 61 | fn sub(self,sub1:T)->Self{ 62 | let mut vec1 = Vector{vec:vec![]}; 63 | for t in self.vec{ 64 | vec1.vec.push(t -sub1); 65 | } 66 | vec1 67 | } 68 | } 69 | impl> Div for Vector{ 70 | type Output = Self; 71 | fn div(self,div1:T)->Self{ 72 | let mut vec1 = Vector{vec:vec![]}; 73 | for t in self.vec{ 74 | vec1.vec.push(t /div1); 75 | } 76 | vec1 77 | } 78 | } 79 | impl+AddAssign> AddAssign for Vector{ 80 | fn add_assign(&mut self,add1:T){ 81 | let mut changer = self.clone(); 82 | for t in &mut changer.vec{ 83 | *t+=add1; 84 | } 85 | *self = changer; 86 | } 87 | } 88 | impl+MulAssign> MulAssign for Vector{ 89 | fn mul_assign(&mut self,mul1:T){ 90 | let mut changer = self.clone(); 91 | for t in &mut changer.vec{ 92 | *t*=mul1; 93 | } 94 | *self = changer; 95 | } 96 | } 97 | impl+SubAssign> SubAssign for Vector{ 98 | fn sub_assign(&mut self,sub1:T){ 99 | let mut changer = self.clone(); 100 | for t in &mut changer.vec{ 101 | *t-=sub1; 102 | } 103 | *self = changer; 104 | } 105 | } 106 | impl+DivAssign> DivAssign for Vector{ 107 | fn div_assign(&mut self,div1:T){ 108 | let mut changer = self.clone(); 109 | for t in &mut changer.vec{ 110 | *t/=div1; 111 | } 112 | *self = changer; 113 | } 114 | } 115 | impl fmt::Display for Vector{ 116 | fn fmt(&self,f: &mut fmt::Formatter<'_>)->fmt::Result{ 117 | for i in self.vec.clone(){ 118 | write!(f, "{}", i)?; 119 | } 120 | Ok(()) 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/vertex.rs: -------------------------------------------------------------------------------- 1 | #[derive(Default, Debug, Clone, Copy,PartialEq)] 2 | pub struct Vertex { 3 | pub position: [f32; 2], 4 | pub color: [f32; 4], 5 | pub tex_coords: [f32;2], 6 | } 7 | vulkano::impl_vertex!(Vertex, position, color,tex_coords); 8 | #[derive(Default, Debug, Clone, Copy,PartialEq)] 9 | pub struct Stext { 10 | pub position: [f32; 2], 11 | pub color: [f32; 4], 12 | pub text: &'static str, 13 | } 14 | --------------------------------------------------------------------------------