blob: 6f94d57a187c80b492a08188ddb7ad30e6727332 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use carnelian::{
App, AppAssistant, ViewAssistant, ViewAssistantContext, ViewAssistantPtr, ViewKey,
ViewMessages, APP,
};
use failure::Error;
use fidl_fuchsia_ui_gfx::{self as gfx, ColorRgba};
use fuchsia_async::{self as fasync, Interval};
use fuchsia_scenic::{Material, Rectangle, SessionPtr, ShapeNode};
use fuchsia_zircon::{ClockId, Duration, Time};
use futures::StreamExt;
use parking_lot::Mutex;
use std::{any::Any, cell::RefCell, f32::consts::PI};
struct SpinningSquareAppAssistant {}
impl AppAssistant for SpinningSquareAppAssistant {
fn setup(&mut self) -> Result<(), Error> {
Ok(())
}
fn create_view_assistant(&mut self, session: &SessionPtr) -> Result<ViewAssistantPtr, Error> {
Ok(Mutex::new(RefCell::new(Box::new(
SpinningSquareViewAssistant {
background_node: ShapeNode::new(session.clone()),
spinning_square_node: ShapeNode::new(session.clone()),
width: 0.0,
height: 0.0,
start: Time::get(ClockId::Monotonic),
},
))))
}
}
struct SpinningSquareViewAssistant {
background_node: ShapeNode,
spinning_square_node: ShapeNode,
width: f32,
height: f32,
start: Time,
}
impl SpinningSquareViewAssistant {
fn setup_timer(key: ViewKey) {
let timer = Interval::new(Duration::from_millis(10));
let f = timer
.map(move |_| {
let mut app = APP.lock();
app.send_message(key, &ViewMessages::Update);
})
.collect::<()>();
fasync::spawn(f);
}
}
impl ViewAssistant for SpinningSquareViewAssistant {
fn setup(&mut self, context: &ViewAssistantContext) -> Result<(), Error> {
context
.import_node
.resource()
.set_event_mask(gfx::METRICS_EVENT_MASK);
context.import_node.add_child(&self.background_node);
let material = Material::new(context.session.clone());
material.set_color(ColorRgba {
red: 0xb7,
green: 0x41,
blue: 0x0e,
alpha: 0xff,
});
self.background_node.set_material(&material);
context.import_node.add_child(&self.spinning_square_node);
let material = Material::new(context.session.clone());
material.set_color(ColorRgba {
red: 0xff,
green: 0x00,
blue: 0xff,
alpha: 0xff,
});
self.spinning_square_node.set_material(&material);
Self::setup_timer(context.key);
Ok(())
}
fn update(&mut self, context: &ViewAssistantContext) -> Result<(), Error> {
self.width = context.width;
self.height = context.height;
const SPEED: f32 = 0.25;
const SECONDS_PER_NANOSECOND: f32 = 1e-9;
let center_x = self.width * 0.5;
let center_y = self.height * 0.5;
self.background_node.set_shape(&Rectangle::new(
context.session.clone(),
self.width,
self.height,
));
self.background_node
.set_translation(center_x, center_y, 0.0);
let square_size = self.width.min(self.height) * 0.6;
let t = ((Time::get(ClockId::Monotonic).nanos() - self.start.nanos()) as f32
* SECONDS_PER_NANOSECOND
* SPEED)
% 1.0;
let angle = t * PI * 2.0;
self.spinning_square_node.set_shape(&Rectangle::new(
context.session.clone(),
square_size,
square_size,
));
self.spinning_square_node
.set_translation(center_x, center_y, 8.0);
self.spinning_square_node
.set_rotation(0.0, 0.0, (angle * 0.5).sin(), (angle * 0.5).cos());
Ok(())
}
fn handle_message(&mut self, _message: &Any) {
// If spinning square had any custom messages they
// would be handled here.
}
}
fn main() -> Result<(), Error> {
let assistant = SpinningSquareAppAssistant {};
App::run(Box::new(assistant))
}