core: Add options to set and force the stage alignment
This commit is contained in:
parent
0c1cd6aa4f
commit
202fe2f1bb
|
@ -95,6 +95,9 @@ pub struct StageData<'gc> {
|
|||
/// The alignment of the stage.
|
||||
align: StageAlign,
|
||||
|
||||
/// Whether to prevent movies from the changing the stage alignment
|
||||
forced_align: bool,
|
||||
|
||||
/// Whether or not a RENDER event should be dispatched on the next render
|
||||
invalidated: bool,
|
||||
|
||||
|
@ -168,6 +171,7 @@ impl<'gc> Stage<'gc> {
|
|||
},
|
||||
invalidated: false,
|
||||
align: Default::default(),
|
||||
forced_align: false,
|
||||
use_bitmap_downsampling: false,
|
||||
view_bounds: Default::default(),
|
||||
window_mode: Default::default(),
|
||||
|
@ -386,9 +390,21 @@ impl<'gc> Stage<'gc> {
|
|||
/// Set the stage alignment.
|
||||
/// This only has an effect if the scale mode is not `StageScaleMode::ExactFit`.
|
||||
pub fn set_align(self, context: &mut UpdateContext<'_, 'gc>, align: StageAlign) {
|
||||
if !self.forced_align() {
|
||||
self.0.write(context.gc_context).align = align;
|
||||
self.build_matrices(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get whether movies are prevented from changing the stage alignment.
|
||||
pub fn forced_align(self) -> bool {
|
||||
self.0.read().forced_align
|
||||
}
|
||||
|
||||
/// Set whether movies are prevented from changing the stage alignment.
|
||||
pub fn set_forced_align(self, context: &mut UpdateContext<'_, 'gc>, force: bool) {
|
||||
self.0.write(context.gc_context).forced_align = force;
|
||||
}
|
||||
|
||||
/// Returns whether bitmaps will use high quality downsampling when scaled down.
|
||||
/// This setting is currently ignored in Ruffle.
|
||||
|
@ -1034,7 +1050,7 @@ bitflags! {
|
|||
///
|
||||
/// This is a bitflags instead of an enum to mimic Flash Player behavior.
|
||||
/// You can theoretically have both TOP and BOTTOM bits set, for example.
|
||||
#[derive(Clone, Copy, Default, Collect)]
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Collect)]
|
||||
#[collect(require_static)]
|
||||
pub struct StageAlign: u8 {
|
||||
/// Align to the top of the viewport.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#[macro_use]
|
||||
mod display_object;
|
||||
pub use display_object::{StageDisplayState, StageScaleMode};
|
||||
pub use display_object::{StageAlign, StageDisplayState, StageScaleMode};
|
||||
|
||||
#[macro_use]
|
||||
extern crate smallvec;
|
||||
|
|
|
@ -840,15 +840,6 @@ impl Player {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn set_stage_align(&mut self, stage_align: &str) {
|
||||
self.mutate_with_update_context(|context| {
|
||||
let stage = context.stage;
|
||||
if let Ok(stage_align) = StageAlign::from_str(stage_align) {
|
||||
stage.set_align(context, stage_align);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_quality(&mut self, quality: StageQuality) {
|
||||
self.mutate_with_update_context(|context| {
|
||||
context.stage.set_quality(context, quality);
|
||||
|
@ -2020,6 +2011,8 @@ pub struct PlayerBuilder {
|
|||
|
||||
// Misc. player configuration
|
||||
autoplay: bool,
|
||||
align: StageAlign,
|
||||
forced_align: bool,
|
||||
scale_mode: StageScaleMode,
|
||||
forced_scale_mode: bool,
|
||||
fullscreen: bool,
|
||||
|
@ -2058,7 +2051,9 @@ impl PlayerBuilder {
|
|||
video: None,
|
||||
|
||||
autoplay: false,
|
||||
scale_mode: StageScaleMode::ShowAll,
|
||||
align: StageAlign::default(),
|
||||
forced_align: false,
|
||||
scale_mode: StageScaleMode::default(),
|
||||
forced_scale_mode: false,
|
||||
fullscreen: false,
|
||||
// Disable script timeout in debug builds by default.
|
||||
|
@ -2139,6 +2134,14 @@ impl PlayerBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the stage scale mode and optionally prevents movies from changing it.
|
||||
#[inline]
|
||||
pub fn with_align(mut self, align: StageAlign, force: bool) -> Self {
|
||||
self.align = align;
|
||||
self.forced_align = force;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets whether the movie will start playing immediately upon load.
|
||||
#[inline]
|
||||
pub fn with_autoplay(mut self, autoplay: bool) -> Self {
|
||||
|
@ -2395,6 +2398,8 @@ impl PlayerBuilder {
|
|||
player_lock.mutate_with_update_context(|context| {
|
||||
Avm2::load_player_globals(context).expect("Unable to load AVM2 globals");
|
||||
let stage = context.stage;
|
||||
stage.set_align(context, self.align);
|
||||
stage.set_forced_align(context, self.forced_align);
|
||||
stage.set_scale_mode(context, self.scale_mode);
|
||||
stage.set_forced_scale_mode(context, self.forced_scale_mode);
|
||||
stage.post_instantiation(context, None, Instantiator::Movie, false);
|
||||
|
|
|
@ -34,14 +34,24 @@ quality-high8x8linear = High (8x8) Linear
|
|||
quality-high16x16 = High (16x16)
|
||||
quality-high16x16linear = High (16x16) Linear
|
||||
|
||||
align = Stage Alignment
|
||||
align-center = Center
|
||||
align-left = Left
|
||||
align-right = Right
|
||||
align-top = Top
|
||||
align-bottom = Bottom
|
||||
align-top-left = Top-Left
|
||||
align-bottom-left = Bottom-Left
|
||||
align-top-right = Top-Right
|
||||
align-bottom-right = Bottom-Right
|
||||
align-force = Force
|
||||
|
||||
scale-mode = Scale Mode
|
||||
scale-mode-exactfit = Exact Fit
|
||||
scale-mode-noborder = No Border
|
||||
scale-mode-noscale = No Scale
|
||||
scale-mode-showall = Show All
|
||||
|
||||
force-scale-mode = Force Scale Mode
|
||||
force-scale-mode-check = Force
|
||||
scale-mode-force = Force
|
||||
|
||||
warn-if-unsupported = Warn if Unsupported
|
||||
warn-if-unsupported-check = Warn
|
||||
|
|
|
@ -3,7 +3,7 @@ use anyhow::Error;
|
|||
use clap::Parser;
|
||||
use ruffle_core::backend::navigator::OpenURLMode;
|
||||
use ruffle_core::config::Letterbox;
|
||||
use ruffle_core::{LoadBehavior, StageScaleMode};
|
||||
use ruffle_core::{LoadBehavior, StageAlign, StageScaleMode};
|
||||
use ruffle_render::quality::StageQuality;
|
||||
use ruffle_render_wgpu::clap::{GraphicsBackend, PowerPreference};
|
||||
use std::path::Path;
|
||||
|
@ -56,6 +56,14 @@ pub struct Opt {
|
|||
#[clap(long, short, default_value = "high")]
|
||||
pub quality: StageQuality,
|
||||
|
||||
/// The alignment of the stage.
|
||||
#[clap(long, short)]
|
||||
pub align: Option<StageAlign>,
|
||||
|
||||
/// Prevent movies from changing the stage alignment.
|
||||
#[clap(long, action)]
|
||||
pub force_align: bool,
|
||||
|
||||
/// The scale mode of the stage.
|
||||
#[clap(long, short, default_value = "show-all")]
|
||||
pub scale: StageScaleMode,
|
||||
|
|
|
@ -6,7 +6,7 @@ use egui::{
|
|||
Align2, Button, Checkbox, ComboBox, DragValue, Grid, Slider, TextEdit, Ui, Widget, Window,
|
||||
};
|
||||
use ruffle_core::backend::navigator::OpenURLMode;
|
||||
use ruffle_core::{LoadBehavior, StageScaleMode};
|
||||
use ruffle_core::{LoadBehavior, StageAlign, StageScaleMode};
|
||||
use ruffle_render::quality::StageQuality;
|
||||
use std::path::Path;
|
||||
use unic_langid::LanguageIdentifier;
|
||||
|
@ -281,7 +281,85 @@ impl OpenDialog {
|
|||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.label(text(&self.locale, "align"));
|
||||
ui.horizontal(|ui| {
|
||||
ComboBox::from_id_source("open-file-advanced-options-align")
|
||||
.selected_text(match self.options.align {
|
||||
StageAlign::TOP => text(&self.locale, "align-top"),
|
||||
StageAlign::BOTTOM => text(&self.locale, "align-bottom"),
|
||||
StageAlign::LEFT => text(&self.locale, "align-left"),
|
||||
StageAlign::RIGHT => text(&self.locale, "align-right"),
|
||||
_ => {
|
||||
let align = self.options.align;
|
||||
if align == StageAlign::TOP | StageAlign::LEFT {
|
||||
text(&self.locale, "align-top-left")
|
||||
} else if align == StageAlign::TOP | StageAlign::RIGHT {
|
||||
text(&self.locale, "align-top-right")
|
||||
} else if align == StageAlign::BOTTOM | StageAlign::LEFT {
|
||||
text(&self.locale, "align-bottom-left")
|
||||
} else if align == StageAlign::BOTTOM | StageAlign::RIGHT {
|
||||
text(&self.locale, "align-bottom-right")
|
||||
} else {
|
||||
text(&self.locale, "align-center")
|
||||
}
|
||||
}
|
||||
})
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::default(),
|
||||
text(&self.locale, "align-center"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::TOP,
|
||||
text(&self.locale, "align-top"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::BOTTOM,
|
||||
text(&self.locale, "align-bottom"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::LEFT,
|
||||
text(&self.locale, "align-left"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::RIGHT,
|
||||
text(&self.locale, "align-right"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::TOP | StageAlign::LEFT,
|
||||
text(&self.locale, "align-top-left"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::TOP | StageAlign::RIGHT,
|
||||
text(&self.locale, "align-top-right"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::BOTTOM | StageAlign::LEFT,
|
||||
text(&self.locale, "align-bottom-left"),
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut self.options.align,
|
||||
StageAlign::BOTTOM | StageAlign::RIGHT,
|
||||
text(&self.locale, "align-bottom-right"),
|
||||
);
|
||||
});
|
||||
ui.checkbox(
|
||||
&mut self.options.force_align,
|
||||
text(&self.locale, "align-force"),
|
||||
);
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.label(text(&self.locale, "scale-mode"));
|
||||
ui.horizontal(|ui| {
|
||||
ComboBox::from_id_source("open-file-advanced-options-scale")
|
||||
.selected_text(match self.options.scale {
|
||||
StageScaleMode::ExactFit => text(&self.locale, "scale-mode-exactfit"),
|
||||
|
@ -311,13 +389,11 @@ impl OpenDialog {
|
|||
text(&self.locale, "scale-mode-showall"),
|
||||
);
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.label(text(&self.locale, "force-scale-mode"));
|
||||
ui.checkbox(
|
||||
&mut self.options.force_scale,
|
||||
text(&self.locale, "force-scale-mode-check"),
|
||||
text(&self.locale, "scale-mode-force"),
|
||||
);
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
ui.label(text(&self.locale, "dummy-external-interface"));
|
||||
|
|
|
@ -11,7 +11,7 @@ use anyhow::anyhow;
|
|||
use ruffle_core::backend::audio::AudioBackend;
|
||||
use ruffle_core::backend::navigator::OpenURLMode;
|
||||
use ruffle_core::config::Letterbox;
|
||||
use ruffle_core::{LoadBehavior, Player, PlayerBuilder, PlayerEvent, StageScaleMode};
|
||||
use ruffle_core::{LoadBehavior, Player, PlayerBuilder, PlayerEvent, StageAlign, StageScaleMode};
|
||||
use ruffle_render::backend::RenderBackend;
|
||||
use ruffle_render::quality::StageQuality;
|
||||
use ruffle_render_wgpu::backend::WgpuRenderBackend;
|
||||
|
@ -31,6 +31,8 @@ pub struct PlayerOptions {
|
|||
pub max_execution_duration: f64,
|
||||
pub base: Option<Url>,
|
||||
pub quality: StageQuality,
|
||||
pub align: StageAlign,
|
||||
pub force_align: bool,
|
||||
pub scale: StageScaleMode,
|
||||
pub volume: f32,
|
||||
pub force_scale: bool,
|
||||
|
@ -54,6 +56,8 @@ impl From<&Opt> for PlayerOptions {
|
|||
max_execution_duration: value.max_execution_duration,
|
||||
base: value.base.clone(),
|
||||
quality: value.quality,
|
||||
align: value.align.unwrap_or_default(),
|
||||
force_align: value.force_align,
|
||||
scale: value.scale,
|
||||
volume: value.volume,
|
||||
force_scale: value.force_scale,
|
||||
|
@ -138,6 +142,7 @@ impl ActivePlayer {
|
|||
.with_max_execution_duration(Duration::from_secs_f64(opt.max_execution_duration))
|
||||
.with_quality(opt.quality)
|
||||
.with_warn_on_unsupported_content(opt.warn_on_unsupported_content)
|
||||
.with_align(opt.align, opt.force_align)
|
||||
.with_scale_mode(opt.scale, opt.force_scale)
|
||||
.with_fullscreen(opt.fullscreen)
|
||||
.with_load_behavior(opt.load_behavior)
|
||||
|
|
|
@ -31,6 +31,7 @@ export const DEFAULT_CONFIG: Required<BaseLoadOptions> = {
|
|||
base: null,
|
||||
menu: true,
|
||||
salign: "",
|
||||
forceAlign: false,
|
||||
quality: "high",
|
||||
scale: "showAll",
|
||||
forceScale: false,
|
||||
|
|
|
@ -414,6 +414,13 @@ export interface BaseLoadOptions {
|
|||
*/
|
||||
salign?: string;
|
||||
|
||||
/**
|
||||
* If set to true, movies are prevented from changing the stage alignment.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
forceAlign?: boolean;
|
||||
|
||||
/**
|
||||
* This is equivalent to Stage.quality.
|
||||
*
|
||||
|
|
|
@ -32,6 +32,7 @@ const defaultConfig = {
|
|||
letterbox: "on",
|
||||
logLevel: "warn",
|
||||
forceScale: true,
|
||||
forceAlign: true,
|
||||
};
|
||||
|
||||
const swfToFlashVersion = {
|
||||
|
|
|
@ -33,6 +33,7 @@ window.addEventListener("DOMContentLoaded", async () => {
|
|||
base: swfUrl.substring(0, swfUrl.lastIndexOf("/") + 1),
|
||||
// Override some default values when playing in the extension player page.
|
||||
letterbox: "on" as Letterbox,
|
||||
forceAlign: true,
|
||||
forceScale: true,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -19,8 +19,8 @@ use ruffle_core::external::{
|
|||
};
|
||||
use ruffle_core::tag_utils::SwfMovie;
|
||||
use ruffle_core::{
|
||||
Color, Player, PlayerBuilder, PlayerEvent, SandboxType, StageScaleMode, StaticCallstack,
|
||||
ViewportDimensions,
|
||||
Color, Player, PlayerBuilder, PlayerEvent, SandboxType, StageAlign, StageScaleMode,
|
||||
StaticCallstack, ViewportDimensions,
|
||||
};
|
||||
use ruffle_render::quality::StageQuality;
|
||||
use ruffle_video_software::backend::SoftwareVideoBackend;
|
||||
|
@ -261,6 +261,8 @@ struct Config {
|
|||
|
||||
salign: Option<String>,
|
||||
|
||||
force_align: bool,
|
||||
|
||||
quality: Option<String>,
|
||||
|
||||
scale: Option<String>,
|
||||
|
@ -580,11 +582,18 @@ impl Ruffle {
|
|||
.and_then(|q| StageQuality::from_str(&q).ok())
|
||||
.unwrap_or(default_quality),
|
||||
)
|
||||
.with_align(
|
||||
config
|
||||
.salign
|
||||
.and_then(|s| StageAlign::from_str(&s).ok())
|
||||
.unwrap_or_default(),
|
||||
config.force_align,
|
||||
)
|
||||
.with_scale_mode(
|
||||
config
|
||||
.scale
|
||||
.and_then(|s| StageScaleMode::from_str(&s).ok())
|
||||
.unwrap_or(StageScaleMode::ShowAll),
|
||||
.unwrap_or_default(),
|
||||
config.force_scale,
|
||||
)
|
||||
.with_frame_rate(config.frame_rate)
|
||||
|
@ -597,7 +606,6 @@ impl Ruffle {
|
|||
// Set config parameters.
|
||||
core.set_background_color(config.background_color);
|
||||
core.set_show_menu(config.show_menu);
|
||||
core.set_stage_align(config.salign.as_deref().unwrap_or(""));
|
||||
core.set_window_mode(config.wmode.as_deref().unwrap_or("window"));
|
||||
callstack = Some(core.callstack());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue