Editor layout fixes from a visual check
No fog while painting, readable tool bars, a two-row spawn block, a dialog that keeps the clicks to itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
abe01ff23e
commit
aacc6a00b2
3 files changed
+77
-41
No files matched your search
+23
-9
@@ -169,7 +169,6 @@ impl BlockEdit {
|
|||||||
if im.button(gfx, Rect::new(CW(), CH() * 0.7, CW() * 12.0, CH() * 1.7), &tr("ed.back")) || (is_key_pressed(KeyCode::Escape) && !im.typing && self.drag.is_none()) {
|
if im.button(gfx, Rect::new(CW(), CH() * 0.7, CW() * 12.0, CH() * 1.7), &tr("ed.back")) || (is_key_pressed(KeyCode::Escape) && !im.typing && self.drag.is_none()) {
|
||||||
back = true;
|
back = true;
|
||||||
}
|
}
|
||||||
gfx.text(&title, CW() * 14.0, CH() * 1.0, S(), FRAME_HI);
|
|
||||||
let mut bx = w - CW();
|
let mut bx = w - CW();
|
||||||
let buttons = [tr("ed.delete"), tr("ed.paste"), tr("ed.copy"), tr("ed.redo"), tr("ed.undo")];
|
let buttons = [tr("ed.delete"), tr("ed.paste"), tr("ed.copy"), tr("ed.redo"), tr("ed.undo")];
|
||||||
let mut pressed_btn = None;
|
let mut pressed_btn = None;
|
||||||
@@ -184,6 +183,10 @@ impl BlockEdit {
|
|||||||
let sw_ = CW() * 18.0;
|
let sw_ = CW() * 18.0;
|
||||||
bx -= sw_ + CW();
|
bx -= sw_ + CW();
|
||||||
im.text_field(gfx, id("bsearch", 0), Rect::new(bx, CH() * 0.7, sw_, CH() * 1.7), &mut self.search, 24);
|
im.text_field(gfx, id("bsearch", 0), Rect::new(bx, CH() * 0.7, sw_, CH() * 1.7), &mut self.search, 24);
|
||||||
|
// the script's name, as much as fits before the search field
|
||||||
|
let room = ((bx - CW() * 15.0) / CW()).max(4.0) as usize;
|
||||||
|
let title: String = title.chars().take(room).collect();
|
||||||
|
gfx.text(&title, CW() * 14.0, CH() * 1.0, S(), FRAME_HI);
|
||||||
if self.search.is_empty() && im.focus != Some(id("bsearch", 0)) {
|
if self.search.is_empty() && im.focus != Some(id("bsearch", 0)) {
|
||||||
gfx.text(&tr("ed.search"), bx + CW() * 0.5, CH() * 1.0, S(), DIM);
|
gfx.text(&tr("ed.search"), bx + CW() * 0.5, CH() * 1.0, S(), DIM);
|
||||||
}
|
}
|
||||||
@@ -294,7 +297,9 @@ impl BlockEdit {
|
|||||||
}
|
}
|
||||||
y += CH() * 2.2;
|
y += CH() * 2.2;
|
||||||
}
|
}
|
||||||
gfx.text(&tr("ed.blocks_hint"), CW() * 0.5, h - CH() * 6.0, SMALL(), DIM);
|
for (k, l) in wrap(&tr("ed.blocks_hint"), ((pal_w - CW()) / (GW * SMALL())) as usize).iter().enumerate() {
|
||||||
|
gfx.text(l, CW() * 0.5, h - CH() * 6.0 + k as f32 * GH * SMALL() * 1.2, SMALL(), DIM);
|
||||||
|
}
|
||||||
|
|
||||||
// ---- the script
|
// ---- the script
|
||||||
let ws = Rect::new(pal_w, top, w - pal_w, h - top - CH() * 2.0);
|
let ws = Rect::new(pal_w, top, w - pal_w, h - top - CH() * 2.0);
|
||||||
@@ -418,13 +423,15 @@ impl BlockEdit {
|
|||||||
path.push(k);
|
path.push(k);
|
||||||
let cat = list[k].category();
|
let cat = list[k].category();
|
||||||
let col = cat_color(cat);
|
let col = cat_color(cat);
|
||||||
let header = Rect::new(x, y, w, CH() * ROW);
|
// the spawn block has many fields: two rows
|
||||||
|
let rows = if matches!(list[k], Block::Spawn { .. }) { 2.0 } else { 1.0 };
|
||||||
|
let header = Rect::new(x, y, w, CH() * ROW * rows);
|
||||||
let problem = ctx.problems.iter().find(|(p, _)| *p == path).map(|(_, k)| *k);
|
let problem = ctx.problems.iter().find(|(p, _)| *p == path).map(|(_, k)| *k);
|
||||||
let selected = self.selected.as_ref() == Some(&path);
|
let selected = self.selected.as_ref() == Some(&path);
|
||||||
let found = !ctx.search.is_empty() && (tr(&format!("blk.{}", list[k].kind_name())).to_lowercase().contains(&ctx.search) || block_text(&list[k]).to_lowercase().contains(&ctx.search));
|
let found = !ctx.search.is_empty() && (tr(&format!("blk.{}", list[k].kind_name())).to_lowercase().contains(&ctx.search) || block_text(&list[k]).to_lowercase().contains(&ctx.search));
|
||||||
// slots: upper half before this block, lower half after it
|
// slots: upper half before this block, lower half after it
|
||||||
slots.push((Rect::new(x, y - CH() * 0.3, w, CH() * ROW * 0.5 + CH() * 0.3), lp.to_vec(), k));
|
slots.push((Rect::new(x, y - CH() * 0.3, w, header.h * 0.5 + CH() * 0.3), lp.to_vec(), k));
|
||||||
slots.push((Rect::new(x, y + CH() * ROW * 0.5, w, CH() * ROW * 0.5), lp.to_vec(), k + 1));
|
slots.push((Rect::new(x, y + header.h * 0.5, w, header.h * 0.5), lp.to_vec(), k + 1));
|
||||||
let nested = matches!(list[k], Block::If { .. } | Block::Repeat { .. });
|
let nested = matches!(list[k], Block::If { .. } | Block::Repeat { .. });
|
||||||
// the block: header row with its fields
|
// the block: header row with its fields
|
||||||
draw_block_shape(header, col, selected, found);
|
draw_block_shape(header, col, selected, found);
|
||||||
@@ -433,7 +440,7 @@ impl BlockEdit {
|
|||||||
im.tip(header, &tr(p));
|
im.tip(header, &tr(p));
|
||||||
}
|
}
|
||||||
// grip: drag the block from here
|
// grip: drag the block from here
|
||||||
let grip = Rect::new(x, y, CW() * 1.4, CH() * ROW);
|
let grip = Rect::new(x, y, CW() * 1.4, header.h);
|
||||||
gfx.text("≡", x + CW() * 0.3, y + CH() * 0.6, S(), Color::new(1.0, 1.0, 1.0, 0.6));
|
gfx.text("≡", x + CW() * 0.3, y + CH() * 0.6, S(), Color::new(1.0, 1.0, 1.0, 0.6));
|
||||||
if im.pressed && im.over(grip) {
|
if im.pressed && im.over(grip) {
|
||||||
im.pressed = false;
|
im.pressed = false;
|
||||||
@@ -441,7 +448,7 @@ impl BlockEdit {
|
|||||||
}
|
}
|
||||||
let fy = y + (CH() * ROW - CH() * 1.5) * 0.5;
|
let fy = y + (CH() * ROW - CH() * 1.5) * 0.5;
|
||||||
let mut cx = x + CW() * 1.8;
|
let mut cx = x + CW() * 1.8;
|
||||||
self.block_fields(im, gfx, &mut list[k], &path, &mut cx, fy, ctx);
|
self.block_fields(im, gfx, &mut list[k], &path, &mut cx, fy, x + CW() * 3.0, ctx);
|
||||||
// a click on the block's free area selects it
|
// a click on the block's free area selects it
|
||||||
if im.clicked(header) {
|
if im.clicked(header) {
|
||||||
ops.push(Op::Select(path.clone()));
|
ops.push(Op::Select(path.clone()));
|
||||||
@@ -455,7 +462,7 @@ impl BlockEdit {
|
|||||||
}
|
}
|
||||||
self.help = tr(&format!("blk.help.{}", list[k].kind_name()));
|
self.help = tr(&format!("blk.help.{}", list[k].kind_name()));
|
||||||
}
|
}
|
||||||
y += CH() * ROW;
|
y += header.h;
|
||||||
if nested {
|
if nested {
|
||||||
// the C shape: bodies indented, with an "else" bar for if
|
// the C shape: bodies indented, with an "else" bar for if
|
||||||
let inner_x = x + CW() * 2.5;
|
let inner_x = x + CW() * 2.5;
|
||||||
@@ -496,7 +503,7 @@ impl BlockEdit {
|
|||||||
|
|
||||||
// the fields inside a block's header row
|
// the fields inside a block's header row
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn block_fields(&mut self, im: &mut Im, gfx: &Gfx, b: &mut Block, path: &[usize], cx: &mut f32, y: f32, ctx: &Ctx) {
|
fn block_fields(&mut self, im: &mut Im, gfx: &Gfx, b: &mut Block, path: &[usize], cx: &mut f32, y: f32, x2: f32, ctx: &Ctx) {
|
||||||
let word = |cx: &mut f32, s: &str| {
|
let word = |cx: &mut f32, s: &str| {
|
||||||
gfx.text(s, *cx, y + CH() * 0.25, S(), TXT);
|
gfx.text(s, *cx, y + CH() * 0.25, S(), TXT);
|
||||||
*cx += gfx.measure(s, S()) + CW() * 0.6;
|
*cx += gfx.measure(s, S()) + CW() * 0.6;
|
||||||
@@ -517,6 +524,13 @@ impl BlockEdit {
|
|||||||
word(cx, &tr("blk.w_level"));
|
word(cx, &tr("blk.w_level"));
|
||||||
self.value(im, gfx, level, Ty::Num, path, 3, cx, y, ctx);
|
self.value(im, gfx, level, Ty::Num, path, 3, cx, y, ctx);
|
||||||
self.side_dd(im, gfx, side, false, path, 4, cx, y);
|
self.side_dd(im, gfx, side, false, path, 4, cx, y);
|
||||||
|
// second row: where, and the name
|
||||||
|
let y = y + CH() * ROW;
|
||||||
|
*cx = x2;
|
||||||
|
let word = |cx: &mut f32, s: &str| {
|
||||||
|
gfx.text(s, *cx, y + CH() * 0.25, S(), TXT);
|
||||||
|
*cx += gfx.measure(s, S()) + CW() * 0.6;
|
||||||
|
};
|
||||||
word(cx, &tr("blk.w_at"));
|
word(cx, &tr("blk.w_at"));
|
||||||
let mut opts = vec![tr("blk.place_core"), tr("blk.place_event")];
|
let mut opts = vec![tr("blk.place_core"), tr("blk.place_event")];
|
||||||
opts.extend(ctx.zones.iter().map(|z| trf("blk.place_zone", &[z.clone()])));
|
opts.extend(ctx.zones.iter().map(|z| trf("blk.place_zone", &[z.clone()])));
|
||||||
|
|||||||
+12
-7
@@ -91,6 +91,9 @@ impl MapEdit {
|
|||||||
game.map.activate();
|
game.map.activate();
|
||||||
game.recount();
|
game.recount();
|
||||||
game.ents.retain(|e| e.alive);
|
game.ents.retain(|e| e.alive);
|
||||||
|
// no fog of war while painting (it is worked out again when the map is stored)
|
||||||
|
game.map.explored.clear();
|
||||||
|
game.map.visible.clear();
|
||||||
let (cx, cy) = game.map.core;
|
let (cx, cy) = game.map.core;
|
||||||
let mut cam = Cam::new(cx as f32 + 1.5, cy as f32 + 1.5);
|
let mut cam = Cam::new(cx as f32 + 1.5, cy as f32 + 1.5);
|
||||||
cam.zoom = 28.0;
|
cam.zoom = 28.0;
|
||||||
@@ -653,16 +656,16 @@ impl MapEdit {
|
|||||||
}
|
}
|
||||||
y += CH() * 2.3;
|
y += CH() * 2.3;
|
||||||
// categories as a grid of buttons
|
// categories as a grid of buttons
|
||||||
let cw = (bar_w - CW() * 2.5) / 3.0;
|
let cw = (bar_w - CW() * 2.25) / 2.0;
|
||||||
for (k, c) in CATS.iter().enumerate() {
|
for (k, c) in CATS.iter().enumerate() {
|
||||||
let r = Rect::new(x + (k % 3) as f32 * (cw + CW() * 0.25), y + (k / 3) as f32 * CH() * 1.9, cw, CH() * 1.7);
|
let r = Rect::new(x + (k % 2) as f32 * (cw + CW() * 0.25), y + (k / 2) as f32 * CH() * 1.8, cw, CH() * 1.6);
|
||||||
let name = tr(&format!("ed.cat.{:?}", c).to_lowercase());
|
let name = tr(&format!("ed.cat.{:?}", c).to_lowercase());
|
||||||
if im.select(gfx, r, &name, self.cat == *c, TXT) {
|
if im.select(gfx, r, &name, self.cat == *c, TXT) {
|
||||||
self.cat = *c;
|
self.cat = *c;
|
||||||
self.item = 0;
|
self.item = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y += CH() * 6.0;
|
y += CH() * 1.8 * ((CATS.len() + 1) / 2) as f32 + CH() * 0.4;
|
||||||
// the items of the category
|
// the items of the category
|
||||||
let items: Vec<String> = match self.cat {
|
let items: Vec<String> = match self.cat {
|
||||||
Cat::Terrain => TERRAIN.iter().map(|t| tr(&format!("ed.terrain.{}", t))).collect(),
|
Cat::Terrain => TERRAIN.iter().map(|t| tr(&format!("ed.terrain.{}", t))).collect(),
|
||||||
@@ -780,14 +783,16 @@ impl MapEdit {
|
|||||||
self.mirror = c as u8;
|
self.mirror = c as u8;
|
||||||
}
|
}
|
||||||
bx += CW() * 19.0;
|
bx += CW() * 19.0;
|
||||||
if im.button(gfx, Rect::new(bx, by, CW() * 8.0, CH() * 1.7), &tr("ed.undo")) {
|
let uw = gfx.measure(&tr("ed.undo"), S()) + CW() * 2.0;
|
||||||
|
if im.button(gfx, Rect::new(bx, by, uw, CH() * 1.7), &tr("ed.undo")) {
|
||||||
self.undo();
|
self.undo();
|
||||||
}
|
}
|
||||||
bx += CW() * 8.5;
|
bx += uw + CW() * 0.5;
|
||||||
if im.button(gfx, Rect::new(bx, by, CW() * 8.0, CH() * 1.7), &tr("ed.redo")) {
|
let rw = gfx.measure(&tr("ed.redo"), S()) + CW() * 2.0;
|
||||||
|
if im.button(gfx, Rect::new(bx, by, rw, CH() * 1.7), &tr("ed.redo")) {
|
||||||
self.redo();
|
self.redo();
|
||||||
}
|
}
|
||||||
bx += CW() * 9.0;
|
bx += rw + CW();
|
||||||
let info = trf("ed.map_info", &[self.game.map.w.to_string(), self.game.map.h.to_string(), self.game.ents.iter().filter(|e| e.alive).count().to_string(), self.game.towers.len().to_string()]);
|
let info = trf("ed.map_info", &[self.game.map.w.to_string(), self.game.map.h.to_string(), self.game.ents.iter().filter(|e| e.alive).count().to_string(), self.game.towers.len().to_string()]);
|
||||||
gfx.text(&info, bx, by + CH() * 0.3, SMALL(), DIM);
|
gfx.text(&info, bx, by + CH() * 0.3, SMALL(), DIM);
|
||||||
gfx.text(&tr("ed.map_hint"), bar_w + CW(), sh() - CH() * 1.5, SMALL(), DIM);
|
gfx.text(&tr("ed.map_hint"), bar_w + CW(), sh() - CH() * 1.5, SMALL(), DIM);
|
||||||
|
|||||||
+42
-25
@@ -207,6 +207,13 @@ impl Editor {
|
|||||||
pub fn frame(&mut self, gfx: &Gfx, r3d: &mut R3d, dt: f32, now: f64) -> EdAction {
|
pub fn frame(&mut self, gfx: &Gfx, r3d: &mut R3d, dt: f32, now: f64) -> EdAction {
|
||||||
clear_background(Color::from_rgba(4, 3, 5, 255));
|
clear_background(Color::from_rgba(4, 3, 5, 255));
|
||||||
self.im.begin();
|
self.im.begin();
|
||||||
|
// an open dialog takes the clicks: the page behind it only draws
|
||||||
|
let held = (self.im.pressed, self.im.released, self.im.wheel);
|
||||||
|
if self.open_dialog {
|
||||||
|
self.im.pressed = false;
|
||||||
|
self.im.released = false;
|
||||||
|
self.im.wheel = 0.0;
|
||||||
|
}
|
||||||
let mut act = EdAction::None;
|
let mut act = EdAction::None;
|
||||||
match self.screen {
|
match self.screen {
|
||||||
Screen::Map(i) => {
|
Screen::Map(i) => {
|
||||||
@@ -236,6 +243,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.open_dialog {
|
if self.open_dialog {
|
||||||
|
(self.im.pressed, self.im.released, self.im.wheel) = held;
|
||||||
begin_ui();
|
begin_ui();
|
||||||
if let Some(a) = self.open_screen(gfx) {
|
if let Some(a) = self.open_screen(gfx) {
|
||||||
act = a;
|
act = a;
|
||||||
@@ -263,30 +271,18 @@ impl Editor {
|
|||||||
let mut act = EdAction::None;
|
let mut act = EdAction::None;
|
||||||
let (w, h) = (sw(), sh());
|
let (w, h) = (sw(), sh());
|
||||||
let im = &mut self.im;
|
let im = &mut self.im;
|
||||||
// top bar: name, author, language, file and server buttons
|
// top bar: the title and the buttons, then name, author, language
|
||||||
let bar_h = CH() * 5.0;
|
let bar_h = CH() * 5.0;
|
||||||
panel(gfx, Rect::new(0.0, 0.0, w, bar_h), "");
|
panel(gfx, Rect::new(0.0, 0.0, w, bar_h), "");
|
||||||
gfx.text(&tr("ed.campaign"), CW(), CH() * 0.4, S(), FRAME_HI);
|
gfx.text(&tr("ed.campaign"), CW(), CH() * 0.8, S(), FRAME_HI);
|
||||||
let fw = (CW() * 24.0).min(w * 0.25);
|
|
||||||
label(gfx, CW(), CH() * 2.0, &tr("ed.name"), DIM);
|
|
||||||
im.text_field(gfx, id("cname", 0), Rect::new(CW() * 8.0, CH() * 1.7, fw, CH() * 1.5), &mut self.doc.name, 40);
|
|
||||||
label(gfx, CW(), CH() * 3.5, &tr("ed.author"), DIM);
|
|
||||||
im.text_field(gfx, id("cauthor", 0), Rect::new(CW() * 8.0, CH() * 3.3, fw, CH() * 1.5), &mut self.doc.author, 32);
|
|
||||||
let lx = CW() * 9.0 + fw;
|
|
||||||
label(gfx, lx, CH() * 2.0, &tr("ed.language"), DIM);
|
|
||||||
let langs = languages();
|
|
||||||
let names: Vec<String> = langs.iter().map(|(_, n)| n.clone()).collect();
|
|
||||||
let cur = langs.iter().find(|(c, _)| *c == self.doc.language).map(|(_, n)| n.clone()).unwrap_or_else(|| self.doc.language.clone());
|
|
||||||
if let Some(k) = im.dropdown(gfx, id("clang", 0), Rect::new(lx, CH() * 3.3, CW() * 14.0, CH() * 1.5), &cur, &names) {
|
|
||||||
self.doc.language = langs[k].0.clone();
|
|
||||||
}
|
|
||||||
// buttons on the right
|
|
||||||
let labels = [tr("ed.play"), tr("ed.new"), tr("ed.open"), tr("ed.save_file"), tr("ed.save_server"), tr("ed.close")];
|
let labels = [tr("ed.play"), tr("ed.new"), tr("ed.open"), tr("ed.save_file"), tr("ed.save_server"), tr("ed.close")];
|
||||||
let bw = labels.iter().map(|l| gfx.measure(l, S())).fold(0.0, f32::max) + CW() * 2.0;
|
let mut bx = w - CW();
|
||||||
let mut bx = w - CW() - bw;
|
|
||||||
for k in (0..labels.len()).rev() {
|
for k in (0..labels.len()).rev() {
|
||||||
let r = Rect::new(bx, CH() * 0.6, bw, CH() * 1.7);
|
let bw = gfx.measure(&labels[k], S()) + CW() * 2.0;
|
||||||
if im.button(gfx, r, &labels[k]) {
|
bx -= bw;
|
||||||
|
let r = Rect::new(bx, CH() * 0.5, bw, CH() * 1.7);
|
||||||
|
let clicked = if k == 0 { im.button_c(gfx, r, &labels[k], GREEN) } else { im.button(gfx, r, &labels[k]) };
|
||||||
|
if clicked {
|
||||||
match k {
|
match k {
|
||||||
0 => act = EdAction::Play,
|
0 => act = EdAction::Play,
|
||||||
1 => {
|
1 => {
|
||||||
@@ -303,18 +299,39 @@ impl Editor {
|
|||||||
_ => act = EdAction::Close,
|
_ => act = EdAction::Close,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bx -= bw + CW() * 0.5;
|
bx -= CW() * 0.5;
|
||||||
}
|
}
|
||||||
|
let y2 = CH() * 2.9;
|
||||||
|
let fw = (CW() * 22.0).min(w * 0.2);
|
||||||
|
let mut x = CW();
|
||||||
|
label(gfx, x, y2 + CH() * 0.25, &tr("ed.name"), DIM);
|
||||||
|
x += gfx.measure(&tr("ed.name"), S()) + CW();
|
||||||
|
im.text_field(gfx, id("cname", 0), Rect::new(x, y2, fw, CH() * 1.5), &mut self.doc.name, 40);
|
||||||
|
x += fw + CW() * 1.5;
|
||||||
|
label(gfx, x, y2 + CH() * 0.25, &tr("ed.author"), DIM);
|
||||||
|
x += gfx.measure(&tr("ed.author"), S()) + CW();
|
||||||
|
im.text_field(gfx, id("cauthor", 0), Rect::new(x, y2, fw * 0.8, CH() * 1.5), &mut self.doc.author, 32);
|
||||||
|
x += fw * 0.8 + CW() * 1.5;
|
||||||
|
label(gfx, x, y2 + CH() * 0.25, &tr("ed.language"), DIM);
|
||||||
|
x += gfx.measure(&tr("ed.language"), S()) + CW();
|
||||||
|
let langs = languages();
|
||||||
|
let names: Vec<String> = langs.iter().map(|(_, n)| n.clone()).collect();
|
||||||
|
let cur = langs.iter().find(|(c, _)| *c == self.doc.language).map(|(_, n)| n.clone()).unwrap_or_else(|| self.doc.language.clone());
|
||||||
|
if let Some(k) = im.dropdown(gfx, id("clang", 0), Rect::new(x, y2, CW() * 14.0, CH() * 1.5), &cur, &names) {
|
||||||
|
self.doc.language = langs[k].0.clone();
|
||||||
|
}
|
||||||
|
x += CW() * 15.5;
|
||||||
let mut publ = self.published;
|
let mut publ = self.published;
|
||||||
if self.server_id.is_some() && im.toggle(gfx, w - CW() * 2.0 - bw * 3.5, CH() * 3.1, &tr("ed.published"), &mut publ) {
|
if self.server_id.is_some() && im.toggle(gfx, x, y2, &tr("ed.published"), &mut publ) {
|
||||||
self.published = publ;
|
self.published = publ;
|
||||||
act = EdAction::Publish(publ);
|
act = EdAction::Publish(publ);
|
||||||
}
|
}
|
||||||
let add = Rect::new(w - CW() - bw, CH() * 3.0, bw, CH() * 1.7);
|
let al = tr("ed.add_mission");
|
||||||
if im.button(gfx, add, &tr("ed.add_mission")) {
|
let aw = gfx.measure(&al, S()) + CW() * 2.0;
|
||||||
|
if im.button(gfx, Rect::new(w - CW() - aw, y2 - CH() * 0.1, aw, CH() * 1.7), &al) {
|
||||||
let n = self.doc.missions.len();
|
let n = self.doc.missions.len();
|
||||||
self.doc.add_mission();
|
self.doc.add_mission();
|
||||||
self.doc.missions[n].pos = (-self.graph.pan.x / CW() * 0.0 + 40.0 + (n % 5) as f32 * 220.0, 40.0 + (n / 5) as f32 * 140.0);
|
self.doc.missions[n].pos = (40.0 + (n % 5) as f32 * 220.0, 40.0 + (n / 5) as f32 * 140.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the canvas: cards and arrows
|
// the canvas: cards and arrows
|
||||||
|
|||||||
Reference in new issue
Block a user