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
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
#![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 extension to cargo
running:
```sh
cargo install cargo-rin
```

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

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

Which will create a default empty project. For more options run
```sh
cargo rin --help
```

## 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: &mut window::Window){

    }

    fn draw(&mut self, gl: &gl::Renderer, window: &window::Window){
        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(&BLACK);
        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()
    .try_iter();

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_moved = window.event_stream()
    .mouse()
    .moved()
    .try_iter();

while !window.should_close(){
...

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

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

Instead of an iterator sometimes you just want to keep the current value that an event stream has
sent. For that we can use properties:

```rust
let mouse_pos = window.event_stream()
    .mouse()
    .moved()
    .to_property(pnt2(0., 0.));

while !window.should_close(){
...

    println!("pos {:?}", *mouse_pos);
}
```

Note how in this case we dereference the property in order to get it's internal value. We could also
simply call `.value()` on it.

Rin's event iterators are thread safe (Send not Sync) so they can be stored on an object an sent to
a different thread. Properties, though, are not so trying to use them from a different thread that
the one they were created from will fail to compile.

If we need similar functionality to a property but across threads we can use a `Parameter` instead

```rust
let mouse_pos = window.event_stream()
    .mouse()
    .moved()
    .to_property(pnt2(0., 0.))
    .to_parameter();
```

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.

## Mutiny template

One of the main tools in the rin ecosytem is Mutiny. Mutiny provides an ECS (Entity Component System)
or data driven programming framework which works in a very different way to the examples above. If
working with rin directly, has an imperative and more or less object oriented approach. Working with
Mutiny implies a more declarative style in which the data we create is managed by the system for a
lot of basic tasks like rendering.

For example in rin to draw a geometry we usually create a mesh, a material and a light and then in
the draw function we explicitly call draw on it. We might probably even put that mesh on a vao to
optimize drawing.

When using Mutiny we first create a scene object and through that scene create a model with a
geometry and material. Also using the scene we would create a light. From there on
the system will draw that object without any explicit draw call. The scene holds those components
and we don't usually care about the details of how they are drawn to the screen. Since the scene
handles all the objects that gives it a much better opportunity for optimization.

In general when working with bigger applications particularly with 3D worlds it's really recomended
to use Mutiny rather than plain rin not only for performance reasons but also because of the rust
ownership model (but really in any language) it is easier to work with the ECS architecgture that
Mutiny uses, than using object oriented programming when there's many objects that would interact
with each other in a traditional OO application.

This is an example of the setup functions of a Mutiny application that creates hundreds of spheres
reusing the geometry and material:

```rust
fn create_entities(scene: &mut mutiny::Scene){
    let sphere = rin::graphics::sphere_texcoords(0.1, 20, 20);
    let sphere = scene.add_mesh(sphere);

    let material = mutiny::material::StandardMaterialBuilder::default()
        .color(RED)
        .roughness(0.9)
        .build();
    let material = scene.register_material("material", material);

    for y in (-60 .. 60).step_by(2){
        let fy = y as f32 / 10.;
        for x in (-100 .. 100).step_by(2){
            let fx = x as f32 / 10.;
            scene.add_model(&format!("sphere{}_{}", x,y))
                .geometry(sphere)
                .material(material)
                .transformation(pnt3(fx, fy, 0.))
                .build();
        }
    }

    let _light = scene.add_directional_light("DirLight")
        .transformation(Node::new_look_at(pnt3(3., 3., 3.), Pnt3::origin(), Vec3::y()))
        .build();
}
```

You can start a new Mutiny application using:

```rust
cargo rin new --mutiny project_path
```

To learn more about Mutiny you can check the specific documentation for it's crate:
[https://rin.rs/doc/mutiny](https://rin.rs/doc/mutiny)

## 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="gl", feature="webgl"))]
compile_error!("Error: gl and webgl features can't be enabled at the same time");
#[cfg(all(feature="gles", feature="webgl"))]
compile_error!("Error: gles and webgl 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(feature="rin-app")]
#[doc(inline)]
pub use rin_app as app;
#[cfg(feature="rin-gl")]
#[doc(inline)]
pub use rin_gl as gl;
#[doc(inline)]
pub use rin_graphics as graphics;
#[doc(inline)]
pub use rin_math as math;
#[doc(inline)]
pub use rin_util as util;
#[doc(inline)]
pub use rin_window as window;
#[cfg(feature="rin-video")]
#[doc(inline)]
pub use rin_video as video;
#[cfg(feature="rin-scene")]
#[doc(inline)]
pub use rin_scene as scene;
#[cfg(feature="rinecs")]
#[doc(inline)]
pub use rinecs as ecs;
#[cfg(feature="rin-gui")]
#[doc(inline)]
pub use rin_gui as gui;
#[cfg(feature="rin-material")]
#[doc(inline)]
pub use rin_material as material;
#[cfg(feature="rin-blender")]
#[doc(inline)]
pub use rin_blender as blender;
#[cfg(feature="rin-postpo")]
#[doc(inline)]
pub use rin_postpo as postpo;
#[doc(inline)]
pub use color;
#[doc(inline)]
pub use seitan as events;

pub use rin_util::{Error, Result};

/// 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 color::{ToRgba, ToRgb, ToXyz, ToYxy, ToLab};

    // import traits
    pub use crate::graphics::{CameraExt, CameraPerspective, CameraOrthographic, RectToMesh};
    pub use crate::window::{WindowExt, Events};
    pub use crate::window::events::{KeyEvents, MouseEvents, WindowEvents};
    #[cfg(feature="video")]
    pub use crate::video::Video;
    pub use crate::graphics::{NodeRef, NodeMut, InsidePolygon, GeometryIterator};
    #[cfg(all(feature="rin-gl", any(feature = "emscripten_window", feature = "glfw_window")))]
    pub use crate::app::ApplicationCallbacks;
    pub use crate::util::LogErr;
    pub use crate::events::{StreamExt, ParamsDefault};
    pub use crate::math::{InsideRect};

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

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

    use color;
    pub static RINRED:                  color::Rgb<u8> = color::Rgb::new(0xFF, 0x00, 0x4C);
    pub static RINGREEN:                color::Rgb<u8> = color::Rgb::new(0x00, 0xFF, 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); }
}