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
// window.rs -- Aldaron's Device Interface / Screen
// Copyright (c) 2017-2018  Jeron A. Lau <jeron.lau@plopgrizzly.com>
// Licensed under the MIT LICENSE

use adi_clock::{ Timer, Pulse, Clock };
use Input;
use adi_gpu::{ Display, DisplayTrait };
use aci_png;
use Texture;
use afi::Graphic;

/// A builder for `Window`.
pub struct WindowBuilder {
	fog: Option<(f32, f32)>,
	rgb: (f32, f32, f32),
	name: String,
	icon: Option<Graphic>,
}

impl WindowBuilder {
	/// A new `WindowBuilder`.
	pub fn new(name: &str, icon: Option<Graphic>) -> Self {
		WindowBuilder {
			fog: None,
			rgb: (1.0, 1.0, 1.0),
			name: name.to_string(),
			icon,
		}
	}

	/// Set fog (distance, depth), off by default.
	pub fn fog(mut self, fog: (f32, f32)) -> Self {
		self.fog = Some(fog);
		self
	}

	/// Set background color, white by default.
	pub fn background(mut self, rgb: (f32, f32, f32)) -> Self {
		self.rgb = rgb;
		self
	}

	/// Finish building the `Window`.
	pub fn finish(self) -> Window {
		let mut native = if let Some(i) = self.icon {
			Display::new(&self.name, i)
		} else {
			let logo = aci_png::decode(
				include_bytes!("res/logo.png"))
				.unwrap();
			Display::new(&self.name, logo)
		}.unwrap();

		let button = Texture(native.texture(
			aci_png::decode(include_bytes!("gui/res/button.png"))
				.unwrap()));

		native.color(self.rgb);
		native.fog(self.fog);

		Window {
			window: native, time: (Timer::new(1.0 / 60.0), 0.0),
			clock: Clock::new(), since_clock: 0.0, since_frame: 0.0,
			minsize: (64, (0.0, 0.0)), aspect: 0.0, button: button,
			seconds: 0.0, fps_counter: 0, fps: 0
		}
	}
}

/// Window represents a connection to a display that can also recieve input.
pub struct Window {
	pub(crate) window: Display,
	time: (Timer, f32),
	clock: Clock,
	since_clock: f32,
	since_frame: f32,
	minsize: (u32, (f32, f32)),
	aspect: f32,
	// Frame Rate Counting
	seconds: f32,
	fps_counter: u16,
	fps: u16,
	// Button Texture
	pub(crate) button: Texture,
}

pub trait WindowFunctions {
	fn unit_ratio(&self) -> f32;
	fn toggle_fullscreen(&mut self) -> ();
	fn wh(&self) -> (u32, u32);
}

impl WindowFunctions for Window {
	fn unit_ratio(&self) -> f32 {
		self.aspect
	}

	fn toggle_fullscreen(&mut self) -> () {
//		self.window.fullscreen();
	}

	fn wh(&self) -> (u32, u32) {
		self.window.wh()
	}
}

impl Window {
	/// Update fog distance.
	pub fn fog(&mut self, fog: Option<(f32, f32)>) {
		self.window.fog(fog);
	}

	/// Set the background color of the window.
	pub fn background(&mut self, rgb: (f32, f32, f32)) -> () {
		self.window.color(rgb);
	}

	/// Adjust the location and direction of the camera.
	pub fn camera(&mut self, xyz: (f32,f32,f32), rotate_xyz: (f32,f32,f32)) {
		self.window.camera(xyz, rotate_xyz);
	}

	/// Get the minimal x and y dimension for a widget.
	pub fn unit_size(&self) -> (f32, f32) {
		self.minsize.1
	}

	/// Update the window and return the user input.  This should run in a
	/// loop.  Returns `None` when done looping through input.  After `None`
	/// is returned, the next call will update the screen.
	pub fn update(&mut self) -> Option<Input> {
		// TODO: Automatically decrease to 30fps if needed.
		// self.time.1 = self.time.0.wait(); // 60 fps
		// Update Screen
		let mut input = self.window.update();

		if input == None && self.aspect == 0.0 {
			input = Some(Input::Resize);
		}

		if input == Some(Input::Resize) {
			let wh = self.wh();
			let (w, h) = (wh.0 as f32, wh.1 as f32);

			self.window.resize(wh);

			(self.minsize.1).0 = 2.0 * (self.minsize.0 as f32) / w;
			(self.minsize.1).1 = 2.0 * (self.minsize.0 as f32) / h;
			self.aspect = h / w;
		}

		// Update how much time has passed since previous frame.
		if input.is_none() {
			let old_time = self.since_clock;
			self.since_clock = self.clock.since();
			self.since_frame = self.since_clock - old_time;
		}

		// Count FPS
		self.fps_counter += 1;

		if self.since_clock >= self.seconds {
			self.fps = self.fps_counter;
			self.fps_counter = 0;
			self.seconds += 1.0;
		}

		input
	}

	/// Returns a number between 0-1. This function is used for animations.
	/// It will take rate_spr seconds to go from 0 to 1. 
	pub fn pulse_half_linear(&self, rate_spr: f32) -> f32 {
		self.time.1.pulse_half_linear(rate_spr)
	}

	/// Returns a number between 0-1. This function is used for animations.
	/// It will take rate_spr seconds to go from 0 to 1 and back to 0.
	pub fn pulse_full_linear(&self, rate_spr: f32) -> f32 {
		self.time.1.pulse_full_linear(rate_spr)

	}

	/// Returns a number between 0-1. This function is used for animations.
	/// It will take rate_spr seconds to go from 0 to 1. It uses cosine
	/// underneath to make the animation look smooth, by making the
	/// beginning and end of the animation slower than the middle.
	pub fn pulse_half_smooth(&self, rate_spr: f32) -> f32 {
		self.time.1.pulse_half_smooth(rate_spr)
	}

	/// Returns a number between 0-1. This function is used for animations.
	/// It will take rate_spr seconds to go from 0 to 1 and back to 0. It
	/// uses cosine underneath to make the animation look smooth, by making
	/// the beginning and end of the animation slower than the middle.
	pub fn pulse_full_smooth(&self, rate_spr: f32) -> f32 {
		self.time.1.pulse_full_smooth(rate_spr)
	}

	/// Get the time passed since the previous window frame.
	pub fn since(&self) -> f32 {
		self.since_frame
	}

	/// Return the current number of FPS the window is running at.
	pub fn fps(&self) -> (u16, bool) {
		(self.fps, self.fps_counter == 0)
	}
}

impl Drop for Window {
	fn drop(&mut self) -> () {
//		renderer::close(&mut self.vw);
		println!("adi_screen: Quit.");
	}
}