Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to show dialogs in Ruffle (show on top of player in web) #2021

Merged
merged 1 commit into from
Dec 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub mod log;
pub mod navigator;
pub mod render;
pub mod storage;
pub mod ui;
22 changes: 22 additions & 0 deletions core/src/backend/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub trait UiBackend {
fn message(&self, message: &str);
}

/// UiBackend that does mostly nothing
pub struct NullUiBackend {}

impl NullUiBackend {
pub fn new() -> Self {
Self {}
}
}

impl UiBackend for NullUiBackend {
fn message(&self, _message: &str) {}
}

impl Default for NullUiBackend {
fn default() -> Self {
NullUiBackend::new()
}
}
27 changes: 19 additions & 8 deletions core/src/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::backend::locale::LocaleBackend;
use crate::backend::navigator::{NavigatorBackend, RequestOptions};
use crate::backend::storage::StorageBackend;
use crate::backend::{
audio::AudioBackend, log::LogBackend, render::Letterbox, render::RenderBackend,
audio::AudioBackend, log::LogBackend, render::Letterbox, render::RenderBackend, ui::UiBackend,
};
use crate::context::{ActionQueue, ActionType, RenderContext, UpdateContext};
use crate::display_object::{EditText, MorphShape, MovieClip};
Expand All @@ -23,7 +23,7 @@ use crate::prelude::*;
use crate::property_map::PropertyMap;
use crate::tag_utils::SwfMovie;
use crate::transform::TransformStack;
use crate::vminterface::Instantiator;
use crate::vminterface::{AvmType, Instantiator};
use enumset::EnumSet;
use gc_arena::{make_arena, ArenaParameters, Collect, GcCell};
use instant::Instant;
Expand Down Expand Up @@ -134,6 +134,7 @@ type Input = Box<dyn InputBackend>;
type Storage = Box<dyn StorageBackend>;
type Locale = Box<dyn LocaleBackend>;
type Log = Box<dyn LogBackend>;
type UI = Box<dyn UiBackend>;

pub struct Player {
/// The version of the player we're emulating.
Expand All @@ -159,6 +160,7 @@ pub struct Player {
input: Input,
locale: Locale,
log: Log,
pub user_interface: UI,
transform_stack: TransformStack,
view_matrix: Matrix,
inverse_view_matrix: Matrix,
Expand Down Expand Up @@ -205,6 +207,7 @@ pub struct Player {
self_reference: Option<Weak<Mutex<Self>>>,
}

#[allow(clippy::too_many_arguments)]
impl Player {
pub fn new(
renderer: Renderer,
Expand All @@ -214,6 +217,7 @@ impl Player {
storage: Storage,
locale: Locale,
log: Log,
user_interface: UI,
) -> Result<Arc<Mutex<Self>>, Error> {
let fake_movie = Arc::new(SwfMovie::empty(NEWEST_PLAYER_VERSION));
let movie_width = 550;
Expand Down Expand Up @@ -280,6 +284,7 @@ impl Player {
input,
locale,
log,
user_interface,
self_reference: None,
system: SystemProperties::default(),
instance_counter: 0,
Expand All @@ -305,10 +310,10 @@ impl Player {

player.build_matrices();
player.audio.set_frame_rate(frame_rate);

let player_box = Arc::new(Mutex::new(player));
let mut player_lock = player_box.lock().unwrap();
player_lock.self_reference = Some(Arc::downgrade(&player_box));

std::mem::drop(player_lock);

Ok(player_box)
Expand Down Expand Up @@ -624,7 +629,7 @@ impl Player {
});
}

// Propagte clip events.
// Propagate clip events.
self.mutate_with_update_context(|context| {
let (clip_event, listener) = match event {
PlayerEvent::KeyDown { .. } => {
Expand Down Expand Up @@ -799,22 +804,28 @@ impl Player {
/// This should only be called once. Further movie loads should preload the
/// specific `MovieClip` referenced.
fn preload(&mut self) {
let mut is_action_script_3 = false;
self.mutate_with_update_context(|context| {
let mut morph_shapes = fnv::FnvHashMap::default();
let root = *context.levels.get(&0).expect("root level");
root.as_movie_clip()
.unwrap()
.preload(context, &mut morph_shapes);

let lib = context
.library
.library_for_movie_mut(root.as_movie_clip().unwrap().movie().unwrap());

is_action_script_3 = lib.avm_type() == AvmType::Avm2;
// Finalize morph shapes.
for (id, static_data) in morph_shapes {
let morph_shape = MorphShape::new(context.gc_context, static_data);
context
.library
.library_for_movie_mut(root.as_movie_clip().unwrap().movie().unwrap())
.register_character(id, crate::character::Character::MorphShape(morph_shape));
lib.register_character(id, crate::character::Character::MorphShape(morph_shape));
}
});
if is_action_script_3 {
self.user_interface.message("This SWF contains ActionScript 3 which is not yet supported by Ruffle. The movie may not work as intended.");
}
}

pub fn run_frame(&mut self) {
Expand Down
2 changes: 2 additions & 0 deletions core/tests/regression_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use ruffle_core::backend::locale::NullLocaleBackend;
use ruffle_core::backend::log::LogBackend;
use ruffle_core::backend::navigator::{NullExecutor, NullNavigatorBackend};
use ruffle_core::backend::storage::MemoryStorageBackend;
use ruffle_core::backend::ui::NullUiBackend;
use ruffle_core::backend::{
audio::NullAudioBackend, input::NullInputBackend, render::NullRenderer,
};
Expand Down Expand Up @@ -694,6 +695,7 @@ fn run_swf(
Box::new(MemoryStorageBackend::default()),
Box::new(NullLocaleBackend::new()),
Box::new(TestLogBackend::new(trace_output.clone())),
Box::new(NullUiBackend::new()),
)?;
player.lock().unwrap().set_root_movie(Arc::new(movie));
player
Expand Down
3 changes: 3 additions & 0 deletions desktop/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod locale;
mod navigator;
mod storage;
mod task;
mod ui;

use crate::custom_event::RuffleEvent;
use crate::executor::GlutinAsyncExecutor;
Expand Down Expand Up @@ -215,6 +216,7 @@ fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
)); //TODO: actually implement this backend type
let input = Box::new(input::WinitInputBackend::new(window.clone()));
let storage = Box::new(DiskStorageBackend::new());
let user_interface = Box::new(ui::DesktopUiBackend::new());
let locale = Box::new(locale::DesktopLocaleBackend::new());
let player = Player::new(
renderer,
Expand All @@ -224,6 +226,7 @@ fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
storage,
locale,
Box::new(NullLogBackend::new()),
user_interface,
)?;
player.lock().unwrap().set_root_movie(Arc::new(movie));
player.lock().unwrap().set_is_playing(true); // Desktop player will auto-play.
Expand Down
23 changes: 23 additions & 0 deletions desktop/src/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use tinyfiledialogs::{message_box_ok, MessageBoxIcon};

use ruffle_core::backend::ui::UiBackend;

pub struct DesktopUiBackend {}

impl DesktopUiBackend {
pub fn new() -> Self {
Self {}
}
}

impl UiBackend for DesktopUiBackend {
fn message(&self, message: &str) {
message_box_ok("Ruffle", message, MessageBoxIcon::Info)
}
}

impl Default for DesktopUiBackend {
fn default() -> Self {
DesktopUiBackend::new()
}
}
2 changes: 2 additions & 0 deletions exporter/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ruffle_core::backend::locale::NullLocaleBackend;
use ruffle_core::backend::log::NullLogBackend;
use ruffle_core::backend::navigator::NullNavigatorBackend;
use ruffle_core::backend::storage::MemoryStorageBackend;
use ruffle_core::backend::ui::NullUiBackend;
use ruffle_core::tag_utils::SwfMovie;
use ruffle_core::Player;
use ruffle_render_wgpu::clap::{GraphicsBackend, PowerPreference};
Expand Down Expand Up @@ -111,6 +112,7 @@ fn take_screenshot(
Box::new(MemoryStorageBackend::default()),
Box::new(NullLocaleBackend::new()),
Box::new(NullLogBackend::new()),
Box::new(NullUiBackend::new()),
)?;

player
Expand Down
19 changes: 19 additions & 0 deletions web/packages/core/src/ruffle-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,25 @@ export class RufflePlayer extends HTMLElement {
}
}

displayMessage(message: string): void {
// Show a dismissible message in front of the player
const div = document.createElement("div");
div.id = "message_overlay";
div.innerHTML = `<div class="message">
<div>
<p>${message}</p>
</div>
<div>
<button id="continue-btn">continue</button>
</div>`;
this.container.prepend(div);
(<HTMLButtonElement>(
this.container.querySelector("#continue-btn")
)).onclick = () => {
div.remove();
};
}

protected debugPlayerInfo(): string {
return `Allows script access: ${this.allowScriptAccess}\n`;
}
Expand Down
36 changes: 35 additions & 1 deletion web/packages/core/src/shadow-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ ruffleShadowTemplate.innerHTML = `
#play_button,
#unmute_overlay,
#unmute_overlay .background,
#panic {
#panic,
#message_overlay {
width: inherit;
height: inherit;
}
Expand Down Expand Up @@ -122,6 +123,39 @@ ruffleShadowTemplate.innerHTML = `
padding: 10px 50px;
}

#message_overlay {
position: absolute;
background-color: #37528C;
color: #FFAD33;
opacity: 1.0;
z-index: 2;
text-align: center;
}

#message_overlay .message {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
padding: 20px;
transform: translate(-50%, -50%);
}

#continue-btn {
cursor: pointer;
background-color: #37528C;
color: #FFAD33;
border: 2px solid #FFAD33;
font-weight: bold;
font-size: 20px;
border-radius: 20px;
padding: 10px;
}

#continue-btn:hover {
background-color: rgba(255, 255, 255, 0.3);
}

#right_click_menu {
color: #FFAD33;
background-color: #37528c;
Expand Down
7 changes: 6 additions & 1 deletion web/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ mod locale;
mod log_adapter;
mod navigator;
mod storage;
mod ui;

use crate::log_adapter::WebLogBackend;
use crate::storage::LocalStorageBackend;
Expand Down Expand Up @@ -96,6 +97,9 @@ extern "C" {

#[wasm_bindgen(method)]
fn panic(this: &JavascriptPlayer, error: &JsError);

#[wasm_bindgen(method, js_name = "displayMessage")]
fn display_message(this: &JavascriptPlayer, message: &str);
}

struct JavascriptInterface {
Expand Down Expand Up @@ -317,7 +321,7 @@ impl Ruffle {

let trace_observer = Arc::new(RefCell::new(JsValue::UNDEFINED));
let log = Box::new(WebLogBackend::new(trace_observer.clone()));

let user_interface = Box::new(ui::WebUiBackend::new(js_player.clone()));
let core = ruffle_core::Player::new(
renderer,
audio,
Expand All @@ -326,6 +330,7 @@ impl Ruffle {
local_storage,
locale,
log,
user_interface,
)?;

// Create instance.
Expand Down
18 changes: 18 additions & 0 deletions web/src/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use super::JavascriptPlayer;
use ruffle_core::backend::ui::UiBackend;

pub struct WebUiBackend {
js_player: JavascriptPlayer,
}

impl WebUiBackend {
pub fn new(js_player: JavascriptPlayer) -> Self {
Self { js_player }
}
}

impl UiBackend for WebUiBackend {
fn message(&self, message: &str) {
self.js_player.display_message(message);
}
}