1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
#![doc(html_favicon_url = "https://rin.rs/favicon.ico")]
/*!
# Introduction

## Installation

In order to use rin you'll need to install rust first:
https://www.rust-lang.org

Once installed you can install rin's project generator
running:
```sh
cargo install rinpg
```

To update to a new version later you can run:
```sh
cargo install --force rinpg
```

You can now create new rin projects by running from a
console:
```sh
rin new project_path
```

Which will create a default empty project. Run rin
with --help for more options.

## Further install

Rust provides autocomplete and static analisys through the
Rust Language Server [https://github.com/rust-lang-nursery/rls](https://github.com/rust-lang-nursery/rls)


To install rls:

```
rustup update
rustup component add rls-preview rust-analysis rust-src
```

Now you can install any IDE with support for rls (usually through extensions)
I've mostly tested rin with visual code and atom.


# Basic example

After creating a new project with the `rin` tool you'll end up
with something that should look like:

```rust
struct App{

}

impl App{
    pub fn new(_gl: &gl::Renderer, _window: &mut window::Window) -> App{
        App{}
    }
}

impl ApplicationCallbacks for App{
    fn update(&mut self, _delta: f64, _gl: &gl::Renderer, _window: &window::WindowT){

    }

    fn draw(&mut self, gl: &gl::Renderer, window: &window::WindowT){
        gl.clear_color(&BLACK);
        gl.clear_depth();
        let _gl = gl.with(Mvp::ortho_top_left(window.viewport()));

    }

    fn key_pressed(&mut self, _key: window::Key, _mods: window::KeyModifiers, _repeat: bool){

    }
    ...
}
```

If you've used other creative frameworks the above should result
familiar with some differences mostly comming from rust's own syntax.

The most important parts in this template are:

- A `new` function where you can initialize anything that you'll
use across your program.
- An `update` function where you can update all the attributes
that need updating like for example animations. The update funciton
in rin receives a `delta` which is the time that the last frame took
in seconds. This is useful to do time based animation. It also receives
a renderer and a window. You usually won't use the renderer in the update
function but sometimes it can be useful. The window can be used to query it's
properties, like it's width, height...
- A `draw` function. This is where you will usually draw things to
the screen. In `draw` you usually use the renderer, called `gl`. In rin
to draw you usually call a function on the renderer. For example:

```rust
gl.draw(&self.geometry);
```
- Callbacks to attend events from mouse, keyboard and others, like `key_pressed`.

## Alternative template

Sometimes types in rust can be quite long and when using the above template
you'll need to specify every type of variables that are created inside
the `App` struct. For variables created inside functions you usually just
use `let` as in:

```
let radius = 10.;
let resolution = 30;
let circle = graphics::circle(radius, resolution);
```

Also because rin tries not to have any global object or function call
you'll need a reference to a renderer in order to draw or to a window
in order to check things like it's size. Because of that some of the
callbacks in the above template are sometimes not so useful.

Another way to use rin is to use the loop template by creating a new
project with the following call:

```sh
rin new --loop project_path
```

Which will create an empty project that looks like:

```rust
fn main() {
    let events = window::EventsPoll::new().unwrap();
    let mut window = window::Builder::new(events.clone())
        .create()
        .unwrap();

    let gl = gl::Renderer::new(&mut window).unwrap();

    while !window.should_close(){
        let _delta = window.curr_frame_time_s();
        window.make_current();
        gl.clear_color(&BLACK);
        gl.clear_depth();
        let _gl = gl.with(Mvp::ortho_top_left(window.viewport()));

        // Your code goes here

        window.swap_buffers();
        events.poll_events();
        window.update();
    }
}
```

In this case the `window` and `gl` variables are always available
and you can listen to whatever events you need by using the facilities
in the events module. You can access window events by using
`Window::event_stream()`.

There's several ways to use events in rin but the most common is to
get an iterator that we can later query for new events inside the
application loop. As in:

```rust
let mouse_pressed = window.event_stream()
    .mouse()
    .pressed()
    .iter_async();

while !window.should_close(){
...

    for (pos, button, mods) in mouse_pressed.by_ref(){
        println!("pos {}", pos);
    }
}
```

Which prints every mouse press position that happened during the current
frame.

Or for example:

```rust
let mouse_pressed = window.event_stream()
    .mouse()
    .moved()
    .iter_async();

while !window.should_close(){
...

    if let Some(pos) = mouse_pressed.by_ref().last(){
        println!("pos {}", pos);
    }
}
```

Which only prints the last position of the mouse during the current frame

This way of using rin also allows more control over the default loop
by not hiding it away from the user and might become the default
template in the future.

## Learning rust

For more information on using rust, you can check the rust book
[https://doc.rust-lang.org/book/second-edition/](https://doc.rust-lang.org/book/second-edition/)

## Examples

You can find examples on how to use rin at: https://...


# API reference


*/
#![recursion_limit="512"]

#[cfg(all(feature="gl", feature="gles"))]
compile_error!("Error: gl and gles features can't be enabled at the same time");
#[cfg(all(feature="image", feature="freeimage"))]
compile_error!("Error: image and freeimage features can't be enabled at the same time");

#[cfg(target_os="android")]
extern crate opengles;
#[cfg(target_os="android")]
extern crate egl;
#[cfg(target_os="android")]
extern crate android;
#[cfg(target_os="android")]
extern crate core;

#[cfg(any(feature="gl", feature="gles", feature="webgl"))]
#[macro_use] extern crate glin;
pub extern crate seitan as events;
#[macro_use] pub extern crate color;
#[macro_use] extern crate bitflags;
#[macro_use] extern crate na;
extern crate angle;
extern crate alga;
extern crate num_traits;
extern crate time;
#[macro_use] extern crate log;
#[cfg(feature="async")]
extern crate futures_core;
#[cfg(feature="async")]
extern crate futures_util;
#[cfg(feature="async")]
extern crate futures_channel;
#[cfg(feature="async")]
extern crate futures_executor;
#[cfg(feature="ttf")]
extern crate freetypegl;
#[cfg(feature="ttf_rusttype")]
pub extern crate rusttype;

#[cfg(feature = "glfw_window")]
extern crate glfw;

#[cfg(feature = "glutin_window")]
extern crate glutin;

#[cfg(all(any(feature = "glfw_window", feature = "glutin_window"), feature="x11"))]
extern crate x11;

#[cfg(all(feature = "glfw_window", feature = "cocoa"))]
extern crate cocoa;

#[cfg(feature = "emscripten_window")]
extern crate emscripten_sys;

#[cfg(feature = "stdweb_window")]
#[macro_use] extern crate stdweb;

extern crate serde;
#[cfg(feature = "stdweb_window")]
#[macro_use] extern crate serde_derive;

#[cfg(all(any(feature="gl", feature="gles", feature="webgl"), any(feature = "emscripten_window", feature = "glfw_window", feature="stdweb_window")))]
pub mod app;
pub mod graphics;
pub mod math;
pub mod util;
pub mod window;
#[cfg(any(feature="gl", feature="gles", feature="webgl"))]
pub mod gl;
#[cfg(all(feature="video", feature="gl", feature="webgl"))]
pub mod video;
// pub mod sensors;
// pub mod io;

#[doc(inline)]
pub use util::{Result, Error};

#[cfg(target_os="android")]
pub mod android;



/// Prelude mod to make it easier to use rin, on applications import preamble
/// like:
///
/// ```rust
/// use rin::prelude::*;
/// ```
///
/// which will import the most used constants, traits...
pub mod prelude{
    // pub use math::*;
    // pub use color::consts::*;
    // pub use color::{Rgba, Rgb, AlphaColor, Hsv};
    pub use color::{ToRgba, ToRgb};

    // import traits
    pub use graphics::CameraT;
    pub use window::{WindowT, Events};
    pub use window::events::{KeyEvents, MouseEvents, WindowEvents};
    #[cfg(feature="video")]
    pub use video::Video;
    pub use graphics::{NodeRef, NodeMut};
    #[cfg(all(any(feature="gl", feature="gles", feature="webgl"), any(feature = "emscripten_window", feature = "glfw_window")))]
    pub use app::ApplicationCallbacks;
    pub use events::StreamT;
    pub use util::LogErr;

    // import rin::gl -> gl
    // pub mod gl{
    //     pub use gl::*;
    // }
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Material;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Light;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::traits::*;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::types::*;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Renderer2d;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Renderer3d;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Render2d;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::Render3d;
    #[cfg(any(feature="gl", feature="gles", feature="webgl"))]
    pub use gl::macros::*;

    // import rin::android -> android
    #[cfg(target_os="android")]
    pub mod android{
        pub use android::*;
    }

    use color;
    pub static RINRED:                  color::Rgb<u8> = color::Rgb { r: 0xFF, g: 0x00, b: 0x4C };
    pub static RINGREEN:                color::Rgb<u8> = color::Rgb { r: 0x00, g: 0xFF, b: 0xB2 };
}

#[cfg(target_os="android")]
pub fn init(android_app: *mut android::AndroidApp) -> Result<(),()>{
    android::set_app(android_app);
    Ok(())
}

#[cfg(target_os="android")]
pub fn quit(){
    let java_vm = android::java_vm();
    if java_vm.is_ok(){
        java_vm.unwrap().detach_current_thread();
    }
    unsafe { libc::exit(0); }
}