This commit is contained in:
Brandon Thomas
2026-10-31 10:54:51 -04:00
6 changed files with 51 additions and 18 deletions
+11 -11
View File
@@ -8,7 +8,7 @@ use crate::EffectcraftApp;
/// Effect names, keyed by effect id (#821).
pub(crate) mod effects;
/// Translations for the panels, tooltips and dialogs below the menu bar (see the module docs).
mod ui;
pub(crate) mod ui;
use effectcraft_engine::menus::{MenuEntry, MenuNode};
#[cfg(not(target_arch = "wasm32"))]
pub(crate) use ui::catalog_characters;
@@ -2912,16 +2912,16 @@ const JAPANESE: &[(&str, &str, &str)] = &[
("view.shareViewOptions", "Share View Options", "表示オプションを共有"),
("", "Switch 3D View", "3Dビューを切り替え"),
("view.3d.activeCamera", "Active Camera", "アクティブカメラ"),
("view.3d.default", "Default", "初期設定"),
("view.3d.front", "Front", "フロント"),
("view.3d.left", "Left", "レフト"),
("view.3d.top", "Top", "トップ"),
("view.3d.back", "Back", "バック"),
("view.3d.right", "Right", "ライト"),
("view.3d.bottom", "Bottom", "ボトム"),
("view.3d.custom1", "Custom View 1", "カスタムビュー1"),
("view.3d.custom2", "Custom View 2", "カスタムビュー2"),
("view.3d.custom3", "Custom View 3", "カスタムビュー3"),
("view.3d.default", "Default", "デフォルト"),
("view.3d.front", "Front", "フロントビュー"),
("view.3d.left", "Left", "レフトビュー"),
("view.3d.top", "Top", "トップビュー"),
("view.3d.back", "Back", "バックビュー"),
("view.3d.right", "Right", "ライトビュー"),
("view.3d.bottom", "Bottom", "ボトムビュー"),
("view.3d.custom1", "Custom View 1", "カスタムビュー 1"),
("view.3d.custom2", "Custom View 2", "カスタムビュー 2"),
("view.3d.custom3", "Custom View 3", "カスタムビュー 3"),
("", "Assign Shortcut to 3D View", "3Dビューにショートカットを割り当て"),
("view.3d.last", "Switch to Last 3D View", "最後の3Dビューに切り替え"),
("view.lookAtSelected", "Look at Selected Layers", "選択したレイヤーを見る"),
+1
View File
@@ -194,6 +194,7 @@ const JAPANESE: &[(&str, &str)] = &[
("About...", "情報..."),
("Active", "使用中"),
("Active Camera", "アクティブカメラ"),
("Active Camera ({})", "アクティブカメラ({})"),
("Alpha", "アルファ"),
("Adapt Feature On Every Frame", "フレームごとに特徴を更新"),
("Adaptive Sample Limit:", "適応サンプル数の上限:"),
+23 -2
View File
@@ -18,6 +18,27 @@ use crate::state::Tool;
use crate::theme::Tokens;
use crate::{EffectcraftApp, widgets};
/// A 3D view's name in the interface's language: the View menu's row for its `view.3d.*` command,
/// else the panel catalog, else the English source. The menu's rows carry After Effects' words —
/// フロントビュー rather than フロント — so the viewer's dropdown and the comp's view label read
/// the same names as View ▸ Switch 3D View.
pub(crate) fn view3d_label(v: View3D) -> &'static str {
let id = match v {
View3D::ActiveCamera => "view.3d.activeCamera",
View3D::Default => "view.3d.default",
View3D::Front => "view.3d.front",
View3D::Left => "view.3d.left",
View3D::Top => "view.3d.top",
View3D::Back => "view.3d.back",
View3D::Right => "view.3d.right",
View3D::Bottom => "view.3d.bottom",
View3D::Custom1 => "view.3d.custom1",
View3D::Custom2 => "view.3d.custom2",
View3D::Custom3 => "view.3d.custom3",
};
crate::i18n::command_label(id, v.label())
}
/// Viewer mapping published each frame (for the control channel and other panels).
#[derive(Clone, Copy, Debug)]
pub struct ViewerMap {
@@ -756,8 +777,8 @@ fn phase_rigs(app: &mut EffectcraftApp, ui: &mut egui::Ui, ectx: &EvalCtx, v: &m
draw_rigs(app, &painter, &map, ectx, &selected, cam_state(ectx), through_active, None);
let view = app.session.state.views3d.get(&cid).map(|v| v.current).unwrap_or_default();
let label = match (view, comp.active_camera(time)) {
(View3D::ActiveCamera, Some(c)) => format!("Active Camera ({})", c.name),
(v, _) => v.label().to_string(),
(View3D::ActiveCamera, Some(c)) => crate::i18n::tr_args("Active Camera ({})", &[&c.name]),
(v, _) => view3d_label(v).to_string(),
};
painter.text(area.left_top() + vec2(12.0, 10.0), Align2::LEFT_TOP, label, Tokens::ui(12.0), t.text_dim);
}
+11
View File
@@ -151,3 +151,14 @@ fn edge_pan_speed_moves_toward_the_edge() {
let corner = edge_pan_speed(area, pos2(950.0, 700.0));
assert!(corner.x < 0.0 && corner.y < 0.0, "{corner:?}");
}
/// Every 3D view names its own `view.3d.*` command: a typo in that mapping would fall back to the
/// English label silently, which is what the viewer showed before (#2691).
#[test]
fn every_3d_view_finds_its_japanese_row() {
crate::i18n::ui::set_current("ja");
for v in View3D::ALL {
assert_ne!(view3d_label(v), v.label(), "{v:?} has no Japanese row");
}
crate::i18n::ui::set_current("en");
}
+3 -3
View File
@@ -101,7 +101,7 @@ pub(super) fn aux_views(
let map = ViewerMap { origin: cr.min, zoom: fit, comp: [cw, ch], area: r };
draw_rigs(app, &p.with_clip_rect(r), &map, &ectx, &selected, cam, through_active, Some(v.id()));
}
let label = if comp.has_3d() { v.label() } else { crate::i18n::tr("Active Camera") };
let label = if comp.has_3d() { super::view3d_label(v) } else { crate::i18n::tr("Active Camera") };
p.text(r.left_bottom() + vec2(8.0, -8.0), Align2::LEFT_BOTTOM, label, Tokens::ui(11.0), Color32::from_white_alpha(200));
app.auto.add(&format!("viewer.view.{}", v.id()), r, label);
if comp.has_3d()
@@ -124,7 +124,7 @@ fn pane_selector(app: &mut EffectcraftApp, ui: &mut egui::Ui, pane: usize, area:
let t = app.tokens;
let r = Rect::from_min_size(area.min + vec2(6.0, 6.0), vec2(124.0, 20.0));
let pid = egui::Id::unique(("viewer-pane-view", pane));
let response = widgets::dropdown(ui, r, crate::i18n::tr(current.label()), &t, pid);
let response = widgets::dropdown(ui, r, super::view3d_label(current), &t, pid);
if response.clicked() {
let open = widgets::popup_is_open(ui, pid);
ui.data_mut(|d| d.insert_temp(pid.with("open"), !open));
@@ -137,7 +137,7 @@ fn pane_selector(app: &mut EffectcraftApp, ui: &mut egui::Ui, pane: usize, area:
ui.set_min_width(124.0);
let mut chosen = None;
for (k, v) in View3D::ALL.iter().enumerate() {
let item = ui.selectable_label(*v == current, crate::i18n::tr(v.label()));
let item = ui.selectable_label(*v == current, super::view3d_label(*v));
app.auto.add(&format!("viewer.view.{pane}.typeItem.{k}"), item.rect, v.label());
if item.clicked() {
chosen = Some(*v);
+2 -2
View File
@@ -896,13 +896,13 @@ fn bottom_bar_contents(app: &mut EffectcraftApp, ui: &mut egui::Ui, bar: Rect, z
let cid = app.session.active_comp_id();
let cur = cid.and_then(|c| app.session.state.views3d.get(&c)).map(|v| v.current).unwrap_or_default();
let r = Rect::from_min_size(pos2(x, cy - 10.0), vec2(118.0, 20.0));
let response = widgets::dropdown(ui, r, cur.label(), &t, egui::Id::unique("vw-cam"));
let response = widgets::dropdown(ui, r, crate::panels::viewer::view3d_label(cur), &t, egui::Id::unique("vw-cam"));
if response.clicked() {
toggle_popup(ui, "vw-cam-pop");
}
app.auto.add_response("viewer.view3d", &response, "3D View");
use effectcraft_engine::render::three_d::View3D;
let items: Vec<(String, bool)> = View3D::ALL.iter().map(|v| (v.label().to_string(), *v == cur)).collect();
let items: Vec<(String, bool)> = View3D::ALL.iter().map(|v| (crate::panels::viewer::view3d_label(*v).to_string(), *v == cur)).collect();
if let Some(i) = popup(app, ui, "vw-cam-pop", r, &items, "view3dItem") {
let _ = app.session.execute("view.set3DView", json!({"view": View3D::ALL[i].id()}));
}