mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-02 22:20:50 -06:00
@@ -40,6 +40,7 @@ mod clip;
|
||||
mod distort;
|
||||
mod group;
|
||||
mod lighting;
|
||||
mod lighting_presets;
|
||||
mod live;
|
||||
mod marks;
|
||||
pub mod pixel;
|
||||
@@ -72,6 +73,7 @@ pub use group::{
|
||||
OutlineHook, PATHFINDER_EFFECTS, evaluate_container, has_container_appearance, has_pathfinder, is_pathfinder, member_shapes, paints,
|
||||
pathfinder_children,
|
||||
};
|
||||
pub use lighting_presets::{LIGHTING_PRESETS, LightingPreset, lighting_preset_params, matching_lighting_preset};
|
||||
pub use live::{expand_live, expand_live_deep, expanded_live_group, text_outliner};
|
||||
pub use marks::{CROP_MARKS, crop_marks_art, has_crop_marks};
|
||||
pub use pixel::{PIXEL_EFFECTS, PixelFx, PixelSpace};
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
//! Original lighting rigs for the publicly documented 3D preset names.
|
||||
//! Adobe publishes the names, not numeric settings. These values are our own; Standard
|
||||
//! retains the existing default. A preset replaces the light rig and ambient only.
|
||||
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_three_d::{DEFAULT_LIGHT, Light};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct LightingPreset {
|
||||
pub id: &'static str,
|
||||
pub label: &'static str,
|
||||
rotation: f64,
|
||||
height: f64,
|
||||
softness: f64,
|
||||
ambient: f64,
|
||||
}
|
||||
|
||||
pub const LIGHTING_PRESETS: [LightingPreset; 4] = [
|
||||
LightingPreset { id: "standard", label: "Standard", rotation: DEFAULT_LIGHT.0, height: DEFAULT_LIGHT.1, softness: 0.0, ambient: 25.0 },
|
||||
LightingPreset { id: "diffuse", label: "Diffuse", rotation: DEFAULT_LIGHT.0, height: DEFAULT_LIGHT.1, softness: 100.0, ambient: 35.0 },
|
||||
LightingPreset { id: "topLeft", label: "Top Left", rotation: 135.0, height: 45.0, softness: 0.0, ambient: 25.0 },
|
||||
LightingPreset { id: "right", label: "Right", rotation: 0.0, height: 30.0, softness: 0.0, ambient: 25.0 },
|
||||
];
|
||||
|
||||
impl LightingPreset {
|
||||
/// The same patch is used by commands and the dialog's preview transaction. Null
|
||||
/// `lights` replaces an explicit multi-light rig with this single white light.
|
||||
pub fn params(self) -> Value {
|
||||
json!({
|
||||
"lights": null, "lightColor": "#ffffff", "lightIntensity": 80.0,
|
||||
"lightRotation": self.rotation, "lightHeight": self.height,
|
||||
"lightSoftness": self.softness, "lightBehind": false, "ambient": self.ambient,
|
||||
})
|
||||
}
|
||||
|
||||
fn matches(self, light: Light, ambient: f64) -> bool {
|
||||
let close = |a: f64, b: f64| (a - b).abs() < 1e-6;
|
||||
!light.behind
|
||||
&& light.color.iter().all(|c| close(*c, 1.0))
|
||||
&& close(light.intensity, 0.8)
|
||||
&& close(light.rotation, self.rotation)
|
||||
&& close(light.height, self.height)
|
||||
&& close(light.softness, self.softness / 100.0)
|
||||
&& close(ambient, self.ambient / 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lighting_preset_params(id: &str) -> Option<Value> {
|
||||
LIGHTING_PRESETS.iter().find(|p| p.id == id).map(|p| p.params())
|
||||
}
|
||||
|
||||
/// Identify the effective rig, including an equivalent explicit single light. Names
|
||||
/// are UI state derived from settings, so edits and older files cannot leave stale names.
|
||||
pub fn matching_lighting_preset(params: &Value) -> Option<usize> {
|
||||
let upgraded = crate::upgrade_params(crate::REVOLVE, params);
|
||||
let o = crate::revolve_options(&upgraded);
|
||||
let light = if let Some(lights) = &o.lights {
|
||||
let mut entries = lights.iter();
|
||||
let light = *entries.next()?;
|
||||
if entries.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
light
|
||||
} else {
|
||||
Light {
|
||||
rotation: o.light_rotation,
|
||||
height: o.light_height,
|
||||
behind: o.light_behind,
|
||||
color: o.light_color,
|
||||
intensity: o.light_intensity,
|
||||
softness: o.light_softness,
|
||||
}
|
||||
};
|
||||
LIGHTING_PRESETS.iter().position(|preset| preset.matches(light, o.ambient))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_are_valid_unique_and_standard_preserves_the_default() {
|
||||
for (i, preset) in LIGHTING_PRESETS.iter().enumerate() {
|
||||
let patch = preset.params();
|
||||
crate::lighting::validate(&patch).unwrap();
|
||||
assert_eq!(lighting_preset_params(preset.id), Some(patch.clone()));
|
||||
assert_eq!(matching_lighting_preset(&patch), Some(i));
|
||||
assert!(!patch.as_object().unwrap().contains_key("shade"));
|
||||
assert!(!patch.as_object().unwrap().contains_key("rotationX"));
|
||||
}
|
||||
assert_eq!(matching_lighting_preset(&json!({})), Some(0));
|
||||
assert!(lighting_preset_params("unknown").is_none());
|
||||
assert_eq!(crate::revolve_options(&LIGHTING_PRESETS[0].params()).light_direction(), crate::revolve_options(&json!({})).light_direction());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_preset_matching_uses_effective_lights_and_detects_custom_edits() {
|
||||
let mut p = LIGHTING_PRESETS[3].params();
|
||||
p["lightColor"] = json!("#ff0000");
|
||||
p["lights"] = json!([{"rotation":0,"height":30}]);
|
||||
assert_eq!(matching_lighting_preset(&p), Some(3), "explicit light overrides stale legacy color");
|
||||
p["lights"][0]["color"] = json!("#4080ff");
|
||||
assert_eq!(matching_lighting_preset(&p), None);
|
||||
p["lights"] = json!([{}, {}]);
|
||||
assert_eq!(matching_lighting_preset(&p), None);
|
||||
for (key, value) in [("ambient", json!(26)), ("lightIntensity", json!(79)), ("lightBehind", json!(true))] {
|
||||
let mut p = LIGHTING_PRESETS[0].params();
|
||||
p[key] = value;
|
||||
assert_eq!(matching_lighting_preset(&p), None, "{key}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_doc,
|
||||
set_params
|
||||
),
|
||||
cmd!(
|
||||
"effect.lightingPreset",
|
||||
"3D Lighting Preset",
|
||||
[],
|
||||
None,
|
||||
"{index: int, preset: standard|diffuse|topLeft|right, item?: appearance item index|null (omitted: the active item, else the object's), ids?|id?: [..], target?: object|contents} replace an applied 3D effect's light rig and ambient with an original lighting preset; preserve shading, geometry and view; all targets must have a 3D effect at index; one undo step → {ids}",
|
||||
has_doc,
|
||||
lighting_preset
|
||||
),
|
||||
cmd!(
|
||||
"effect.expandAppearance",
|
||||
"Expand Appearance",
|
||||
@@ -300,6 +309,30 @@ pub(crate) fn set_params_effects(s: &Session, p: &Value) -> Vec<String> {
|
||||
ids.iter().filter_map(effect).collect()
|
||||
}
|
||||
|
||||
fn lighting_preset(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "effect.lightingPreset";
|
||||
let patch = str_param(p, "preset")
|
||||
.and_then(effects::lighting_preset_params)
|
||||
.ok_or_else(|| bad(C, "preset must be standard, diffuse, topLeft or right"))?;
|
||||
let index = index_param(p, "index", C)?;
|
||||
let item = item_target(s, p, C)?;
|
||||
// Validate the whole selection before changing any object. An unrelated effect or
|
||||
// a missing index must not leave just some objects with a new lighting rig.
|
||||
for id in appearance_targets(s, p)? {
|
||||
let n = s.doc()?.doc.node(id).ok_or(EngineError::NoNode(id))?;
|
||||
let slot = item.effects_item(&n.appearance, C)?;
|
||||
let effect = n.appearance.effects_at(slot).and_then(|fx| fx.get(index));
|
||||
if !effect.is_some_and(|e| effects::is_three_d(&e.id)) {
|
||||
return Err(bad(C, format!("object {} needs a 3D effect at index {index}", id.0)));
|
||||
}
|
||||
}
|
||||
let mut options = p.clone();
|
||||
let map = options.as_object_mut().ok_or_else(|| bad(C, "parameters must be an object"))?;
|
||||
map.remove("preset");
|
||||
map.insert("params".into(), patch);
|
||||
set_params(s, &options)
|
||||
}
|
||||
|
||||
fn set_params(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "effect.setParams";
|
||||
let index = index_param(p, "index", C)?;
|
||||
@@ -673,6 +706,10 @@ fn expand_appearance(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests_lighting_presets.rs"]
|
||||
mod lighting_presets_tests;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::json;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
#![allow(clippy::unwrap_used, clippy::panic)]
|
||||
use serde_json::{Value, json};
|
||||
use vectorcraft_doc::NodeId;
|
||||
use vectorcraft_render::effects::{LIGHTING_PRESETS, matching_lighting_preset};
|
||||
|
||||
use crate::Session;
|
||||
|
||||
fn setup(effect: &str, item: Value) -> (Session, NodeId) {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width":400,"height":400})).unwrap();
|
||||
let id = NodeId(s.execute("path.create", &json!({"d":"M100 100L200 100L200 200L100 200Z"})).unwrap()["id"].as_u64().unwrap());
|
||||
s.execute("paint.setFill", &json!({"color":"#338ad6"})).unwrap();
|
||||
s.execute(
|
||||
"effect.apply",
|
||||
&json!({"effect":effect,"item":item,"params":{
|
||||
"rotationX":13,"rotationY":17,"rotationZ":9,"shade":false,"ambient":17,
|
||||
"lights":[{"color":"#ff8040"},{"color":"#4080ff","rotation":-35}]
|
||||
}}),
|
||||
)
|
||||
.unwrap();
|
||||
(s, id)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_preserve_source_and_view_and_round_trip_in_one_undo_step() {
|
||||
for effect in ["threeD.revolve", "threeD.extrude", "threeD.inflate", "threeD.rotate"] {
|
||||
for (i, preset) in LIGHTING_PRESETS.iter().enumerate() {
|
||||
let (mut s, id) = setup(effect, Value::Null);
|
||||
s.doc_mut().unwrap().mark_saved();
|
||||
let before = s.doc().unwrap().doc.clone();
|
||||
let history = s.doc().unwrap().history.undo.len();
|
||||
let p = json!({"index":0,"item":null,"preset":preset.id});
|
||||
s.check_params("effect.lightingPreset", &p).unwrap();
|
||||
s.execute("effect.lightingPreset", &p).unwrap();
|
||||
let after = s.doc().unwrap().doc.clone();
|
||||
let actual = &after.node(id).unwrap().appearance.effects[0].params;
|
||||
let mut expected = before.node(id).unwrap().appearance.effects[0].params.clone();
|
||||
expected.as_object_mut().unwrap().extend(preset.params().as_object().unwrap().clone());
|
||||
assert_eq!(*actual, expected);
|
||||
assert_eq!(matching_lighting_preset(actual), Some(i));
|
||||
assert_eq!(after.node(id).unwrap().path_data(), before.node(id).unwrap().path_data());
|
||||
assert_eq!(actual["rotationX"], 13);
|
||||
assert_eq!(actual["shade"], false);
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), history + 1);
|
||||
let reopened = vectorcraft_format::load(&vectorcraft_format::save(&after, false)).unwrap();
|
||||
assert_eq!(reopened.node(id).unwrap().appearance.effects[0].params, *actual);
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().doc, before);
|
||||
assert!(!s.doc().unwrap().is_dirty());
|
||||
s.execute("edit.redo", &json!({})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().doc, after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_target_fill_effects_and_reject_invalid_requests_atomically() {
|
||||
let (mut s, id) = setup("threeD.rotate", json!(0));
|
||||
for p in [
|
||||
json!({"index":0,"item":0,"preset":"unknown"}),
|
||||
json!({"index":0,"item":0,"preset":12}),
|
||||
json!({"index":1,"item":0,"preset":"right"}),
|
||||
json!({"index":0,"item":null,"preset":"right"}),
|
||||
json!({"index":0,"item":0,"preset":"right","params":{"ambient":200}}),
|
||||
] {
|
||||
s.doc_mut().unwrap().mark_saved();
|
||||
let before = s.doc().unwrap().doc.clone();
|
||||
let history = s.doc().unwrap().history.undo.len();
|
||||
assert!(s.execute("effect.lightingPreset", &p).is_err(), "{p}");
|
||||
assert_eq!(s.doc().unwrap().doc, before);
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), history);
|
||||
assert!(!s.doc().unwrap().is_dirty());
|
||||
}
|
||||
s.execute("effect.lightingPreset", &json!({"ids":[id.0],"index":0,"item":0,"preset":"topLeft"})).unwrap();
|
||||
let n = s.doc().unwrap().doc.node(id).unwrap();
|
||||
assert!(n.appearance.effects.is_empty());
|
||||
assert_eq!(n.appearance.effects_at(Some(0)).unwrap()[0].params["lightRotation"], 135.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_reject_a_mixed_selection_before_changing_any_effect() {
|
||||
let (mut s, first) = setup("threeD.rotate", Value::Null);
|
||||
let second = s.execute("shape.rectangle", &json!({"x":250,"y":100,"width":80,"height":80})).unwrap()["id"].clone();
|
||||
s.execute("effect.apply", &json!({"effect":"path.offsetPath","item":null})).unwrap();
|
||||
s.execute("select.set", &json!({"ids":[first.0,second]})).unwrap();
|
||||
s.doc_mut().unwrap().mark_saved();
|
||||
let before = s.doc().unwrap().doc.clone();
|
||||
let history = s.doc().unwrap().history.undo.len();
|
||||
assert!(s.execute("effect.lightingPreset", &json!({"index":0,"item":null,"preset":"right"})).is_err());
|
||||
assert_eq!(s.doc().unwrap().doc, before);
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), history);
|
||||
assert!(!s.doc().unwrap().is_dirty());
|
||||
}
|
||||
@@ -293,6 +293,7 @@ fn lighting_controls(ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
}
|
||||
});
|
||||
ui.add_enabled_ui(d.bool("shade"), |ui| {
|
||||
lighting_presets(ui, d);
|
||||
light_list(ui, d);
|
||||
let mut selected = selected_light(d);
|
||||
let before = light_record(&selected);
|
||||
@@ -310,6 +311,26 @@ fn lighting_controls(ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
});
|
||||
}
|
||||
|
||||
fn lighting_presets(ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
let names = [tl!("Standard"), tl!("Diffuse"), tl!("Top Left"), tl!("Right")];
|
||||
let current = vectorcraft_effects::matching_lighting_preset(&super::form::params(d));
|
||||
ui.horizontal(|ui| {
|
||||
ui.spacing_mut().item_spacing.x = 6.0;
|
||||
label(ui, tl!("Presets"));
|
||||
let shown = current.and_then(|i| names.get(i).copied()).unwrap_or(tl!("Custom"));
|
||||
if let Some(preset) = widgets::dropdown(ui, "three-d-lighting-presets", shown, &names, VALUE_W + rail_width(ui) + 6.0)
|
||||
.and_then(|i| vectorcraft_effects::LIGHTING_PRESETS.get(i))
|
||||
&& let Some(patch) = preset.params().as_object()
|
||||
{
|
||||
d.fields.extend(patch.clone());
|
||||
d.fields.insert("__light".into(), json!(0));
|
||||
ui.memory_mut(|m| m.stop_text_input());
|
||||
super::revolve_gizmo::clear(ui.ctx());
|
||||
}
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
}
|
||||
|
||||
const LIGHT_KEYS: [(&str, &str); 6] = [
|
||||
("color", "lightColor"),
|
||||
("intensity", "lightIntensity"),
|
||||
|
||||
@@ -438,3 +438,63 @@ fn light_list_stops_at_ten_and_cancel_restores_the_source() {
|
||||
dialogs::cancel(&mut h.app);
|
||||
assert_eq!(h.app.session.doc().unwrap().doc, before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_preview_custom_edits_reset_and_commit_as_one_undo_step() {
|
||||
for effect in [REVOLVE, EXTRUDE, INFLATE, vectorcraft_effects::ROTATE] {
|
||||
let mut h = Harness::with("M100 100L200 100L200 200L100 200Z", effect, vec2(1280.0, 900.0));
|
||||
let before = h.app.session.doc().unwrap().doc.clone();
|
||||
h.settle();
|
||||
h.click(h.rect("Lighting").center());
|
||||
let view = h.app.ui.dialog.as_ref().unwrap().fields["rotationX"].clone();
|
||||
h.click(h.rect("Standard").center());
|
||||
h.click(h.rect("Right").center());
|
||||
assert_eq!(h.value("lightRotation"), 0.0);
|
||||
assert_eq!(h.app.ui.dialog.as_ref().unwrap().fields["rotationX"], view);
|
||||
h.drag(h.rect("Height").center(), vec2(20.0, 0.0));
|
||||
assert!(!h.rect("Custom").is_negative());
|
||||
h.click(h.rect("Custom").center());
|
||||
h.click(h.rect("Diffuse").center());
|
||||
assert_eq!(h.value("lightSoftness"), 100.0);
|
||||
assert_eq!(h.value("ambient"), 35.0);
|
||||
h.click(h.rect("Add Light").center());
|
||||
assert!(!h.rect("Custom").is_negative());
|
||||
h.click(h.rect("Custom").center());
|
||||
h.click(h.rect("Top Left").center());
|
||||
let d = h.app.ui.dialog.as_ref().unwrap();
|
||||
assert!(d.fields["lights"].is_null());
|
||||
assert_eq!(d.fields["__light"], 0);
|
||||
assert_eq!(d.f64("lightRotation", 0.0), 135.0);
|
||||
h.click(h.response("revolve-reset-all").center());
|
||||
assert!(!h.rect("Standard").is_negative());
|
||||
h.click(h.rect("Standard").center());
|
||||
h.click(h.rect("Right").center());
|
||||
dialogs::confirm(&mut h.app).unwrap();
|
||||
h.app.run("edit.undo", json!({})).unwrap();
|
||||
assert_eq!(h.app.session.doc().unwrap().doc, before);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lighting_presets_cancel_restores_an_existing_custom_light_rig() {
|
||||
let mut h = Harness::new(vec2(1280.0, 900.0));
|
||||
h.settle();
|
||||
dialogs::confirm(&mut h.app).unwrap();
|
||||
h.app
|
||||
.run(
|
||||
"effect.setParams",
|
||||
json!({"index":0,"item":null,"params":{
|
||||
"ambient":19,"lights":[{"color":"#ff8040"},{"color":"#4080ff"}]
|
||||
}}),
|
||||
)
|
||||
.unwrap();
|
||||
let before = h.app.session.doc().unwrap().doc.clone();
|
||||
h.app.run("effect.dialog", json!({"effect":REVOLVE,"index":0,"item":null})).unwrap();
|
||||
h.settle();
|
||||
h.click(h.rect("Lighting").center());
|
||||
h.click(h.rect("Custom").center());
|
||||
h.click(h.rect("Right").center());
|
||||
assert_ne!(h.app.session.doc().unwrap().doc, before);
|
||||
dialogs::cancel(&mut h.app);
|
||||
assert_eq!(h.app.session.doc().unwrap().doc, before);
|
||||
}
|
||||
|
||||
@@ -5065,6 +5065,9 @@ theme Appearance Външен вид
|
||||
Softness Мекота
|
||||
Ambient Light Околна светлина
|
||||
Light behind the object Светлина зад обекта
|
||||
3D Lighting Preset Предварителна настройка за 3D осветление
|
||||
Standard Стандартно
|
||||
Diffuse Дифузно
|
||||
# 3D light management.
|
||||
Lights Светлини
|
||||
Add Light Добавяне на светлина
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5165,6 +5165,9 @@ mark-style Japanese Japonské
|
||||
Softness Měkkost
|
||||
Ambient Light Okolní světlo
|
||||
Light behind the object Světlo za objektem
|
||||
3D Lighting Preset Předvolba 3D osvětlení
|
||||
Standard Standardní
|
||||
Diffuse Rozptýlené
|
||||
# 3D light management.
|
||||
Lights Světla
|
||||
Add Light Přidat světlo
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4828,6 +4828,9 @@ mark-style Japanese Japansk
|
||||
Softness Blødhed
|
||||
Ambient Light Omgivelseslys
|
||||
Light behind the object Lys bag objektet
|
||||
3D Lighting Preset Forudindstilling for 3D-belysning
|
||||
Standard Standard
|
||||
Diffuse Diffust
|
||||
# 3D light management.
|
||||
Lights Lyskilder
|
||||
Add Light Tilføj lyskilde
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4741,6 +4741,9 @@ effect Soft Weich
|
||||
Softness Weichheit
|
||||
Ambient Light Umgebungslicht
|
||||
Light behind the object Licht hinter dem Objekt
|
||||
3D Lighting Preset 3D-Beleuchtungsvorgabe
|
||||
Standard Standard
|
||||
Diffuse Diffus
|
||||
# 3D light management.
|
||||
Lights Lichter
|
||||
Add Light Licht hinzufügen
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4872,6 +4872,9 @@ theme Appearance Εμφάνιση
|
||||
to set spacing and orientation για ορισμό απόστασης και προσανατολισμού
|
||||
: :
|
||||
Light behind the object Φως πίσω από το αντικείμενο
|
||||
3D Lighting Preset Προεπιλογή φωτισμού 3D
|
||||
Standard Τυπικός
|
||||
Diffuse Διάχυτος
|
||||
# 3D light management.
|
||||
Lights Φώτα
|
||||
Add Light Προσθήκη φωτός
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2031 and column 19.
|
@@ -5106,6 +5106,9 @@ mark-style Japanese Japonesas
|
||||
Softness Suavidad
|
||||
Ambient Light Luz ambiental
|
||||
Light behind the object Luz detrás del objeto
|
||||
3D Lighting Preset Ajuste preestablecido de iluminación 3D
|
||||
Standard Estándar
|
||||
Diffuse Difusa
|
||||
# 3D light management.
|
||||
Lights Luces
|
||||
Add Light Añadir luz
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5054,6 +5054,9 @@ mark-style Japanese Japanilainen
|
||||
Softness Pehmeys
|
||||
Ambient Light Ympäristövalo
|
||||
Light behind the object Valo objektin takana
|
||||
3D Lighting Preset 3D-valaistuksen esiasetus
|
||||
Standard Vakio
|
||||
Diffuse Hajavalo
|
||||
# 3D light management.
|
||||
Lights Valot
|
||||
Add Light Lisää valo
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5165,6 +5165,9 @@ theme Appearance Apparence
|
||||
Softness Douceur
|
||||
Ambient Light Lumière ambiante
|
||||
Light behind the object Lumière derrière l'objet
|
||||
3D Lighting Preset Préréglage d’éclairage 3D
|
||||
Standard Standard
|
||||
Diffuse Diffus
|
||||
# 3D light management.
|
||||
Lights Lumières
|
||||
Add Light Ajouter une lumière
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5151,6 +5151,9 @@ imageTrace Outline Körvonal
|
||||
Softness Lágyság
|
||||
Ambient Light Környezeti fény
|
||||
Light behind the object Fény az objektum mögött
|
||||
3D Lighting Preset 3D világítási készlet
|
||||
Standard Normál
|
||||
Diffuse Szórt
|
||||
# 3D light management.
|
||||
Lights Fények
|
||||
Add Light Fény hozzáadása
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4828,6 +4828,9 @@ mark-style Japanese Jepang
|
||||
Softness Kelembutan
|
||||
Ambient Light Cahaya ambient
|
||||
Light behind the object Cahaya di belakang objek
|
||||
3D Lighting Preset Preset Pencahayaan 3D
|
||||
Standard Standar
|
||||
Diffuse Difus
|
||||
# 3D light management.
|
||||
Lights Lampu
|
||||
Add Light Tambah Lampu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3801 and column 19.
|
@@ -4775,6 +4775,9 @@ lighting Light Luce
|
||||
Softness Morbidezza
|
||||
Ambient Light Luce ambientale
|
||||
Light behind the object Luce dietro l'oggetto
|
||||
3D Lighting Preset Predefinito illuminazione 3D
|
||||
Standard Standard
|
||||
Diffuse Diffusa
|
||||
# 3D light management.
|
||||
Lights Luci
|
||||
Add Light Aggiungi luce
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4814,6 +4814,9 @@ lighting Light ライト
|
||||
Softness 柔らかさ
|
||||
Ambient Light 環境光
|
||||
Light behind the object オブジェクトの背後のライト
|
||||
3D Lighting Preset 3D ライティングプリセット
|
||||
Standard 標準
|
||||
Diffuse 拡散
|
||||
# 3D light management.
|
||||
Lights ライト一覧
|
||||
Add Light ライトを追加
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4740,6 +4740,9 @@ imageTrace Outline კონტური
|
||||
In the File ფაილში
|
||||
Keys კლავიშები
|
||||
Light behind the object სინათლე ობიექტის უკან
|
||||
3D Lighting Preset 3D განათების წინასწარი პარამეტრი
|
||||
Standard სტანდარტული
|
||||
Diffuse დიფუზური
|
||||
Line {line} სტრიქონი {line}
|
||||
Line {line}: {name}: {status} სტრიქონი {line}: {name}: {status}
|
||||
Needs Attention Only მხოლოდ საყურადღებო
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4738,6 +4738,9 @@ lighting Light 광원
|
||||
Softness 부드러움
|
||||
Ambient Light 주변광
|
||||
Light behind the object 개체 뒤의 조명
|
||||
3D Lighting Preset 3D 조명 사전 설정
|
||||
Standard 표준
|
||||
Diffuse 확산
|
||||
# 3D light management.
|
||||
Lights 광원 목록
|
||||
Add Light 광원 추가
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4840,6 +4840,9 @@ mark-style Japanese Japans
|
||||
Softness Zachtheid
|
||||
Ambient Light Omgevingslicht
|
||||
Light behind the object Licht achter het object
|
||||
3D Lighting Preset Voorinstelling 3D-belichting
|
||||
Standard Standaard
|
||||
Diffuse Diffuus
|
||||
# 3D light management.
|
||||
Lights Lichtbronnen
|
||||
Add Light Lichtbron toevoegen
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5002,6 +5002,9 @@ mark-style Japanese Japońskie
|
||||
Softness Miękkość
|
||||
Ambient Light Światło otoczenia
|
||||
Light behind the object Światło za obiektem
|
||||
3D Lighting Preset Ustawienie oświetlenia 3D
|
||||
Standard Standardowe
|
||||
Diffuse Rozproszone
|
||||
# 3D light management.
|
||||
Lights Światła
|
||||
Add Light Dodaj światło
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4082,6 +4082,9 @@ axis Both Ambos
|
||||
Softness Suavidade
|
||||
Ambient Light Luz ambiente
|
||||
Light behind the object Luz atrás do objeto
|
||||
3D Lighting Preset Predefinição de iluminação 3D
|
||||
Standard Padrão
|
||||
Diffuse Difusa
|
||||
# 3D light management.
|
||||
Lights Luzes
|
||||
Add Light Adicionar luz
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4771,6 +4771,9 @@ lighting Light Свет
|
||||
Softness Мягкость
|
||||
Ambient Light Окружающий свет
|
||||
Light behind the object Свет позади объекта
|
||||
3D Lighting Preset Предустановка 3D освещения
|
||||
Standard Стандартное
|
||||
Diffuse Рассеянное
|
||||
# 3D light management.
|
||||
Lights Источники света
|
||||
Add Light Добавить свет
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5070,6 +5070,9 @@ theme Appearance Utseende
|
||||
Softness Mjukhet
|
||||
Ambient Light Omgivande ljus
|
||||
Light behind the object Ljus bakom objektet
|
||||
3D Lighting Preset Förinställning för 3D-belysning
|
||||
Standard Standard
|
||||
Diffuse Diffust
|
||||
# 3D light management.
|
||||
Lights Ljuskällor
|
||||
Add Light Lägg till ljus
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4755,6 +4755,9 @@ lighting Light Світло
|
||||
Softness М'якість
|
||||
Ambient Light Навколишнє світло
|
||||
Light behind the object Світло позаду об'єкта
|
||||
3D Lighting Preset Попереднє налаштування 3D освітлення
|
||||
Standard Стандартне
|
||||
Diffuse Розсіяне
|
||||
# 3D light management.
|
||||
Lights Джерела світла
|
||||
Add Light Додати світло
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 726 and column 40.
|
@@ -4757,6 +4757,9 @@ theme Appearance Giao diện
|
||||
Softness Độ mềm
|
||||
Ambient Light Ánh sáng môi trường
|
||||
Light behind the object Ánh sáng phía sau đối tượng
|
||||
3D Lighting Preset Thiết lập sẵn ánh sáng 3D
|
||||
Standard Tiêu chuẩn
|
||||
Diffuse Khuếch tán
|
||||
# 3D light management.
|
||||
Lights Danh sách đèn
|
||||
Add Light Thêm đèn
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4003 and column 10.
|
@@ -5030,6 +5030,9 @@ lighting Light 光源
|
||||
Softness 柔和度
|
||||
Ambient Light 环境光
|
||||
Light behind the object 光源位于对象后方
|
||||
3D Lighting Preset 3D 光照预设
|
||||
Standard 标准
|
||||
Diffuse 漫射
|
||||
# 3D light management.
|
||||
Lights 光源列表
|
||||
Add Light 添加光源
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4837,6 +4837,9 @@ lighting Light 光源
|
||||
Softness 柔和度
|
||||
Ambient Light 環境光
|
||||
Light behind the object 光源位於物件後方
|
||||
3D Lighting Preset 3D 光照預設
|
||||
Standard 標準
|
||||
Diffuse 漫射
|
||||
# 3D light management.
|
||||
Lights 光源清單
|
||||
Add Light 新增光源
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
Reference in New Issue
Block a user