chiark / gitweb /
Autoraise on ungrab, where applicable
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 4 Apr 2021 23:44:36 +0000 (00:44 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 5 Apr 2021 00:47:26 +0000 (01:47 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/api.rs
templates/script.ts

index e72991f1e00431aee527e9f0810c283870d7f1ab..7a066157a59caa1d8e04759a8c39693379cfaa7f 100644 (file)
@@ -342,6 +342,7 @@ api_route!{
 api_route!{
   api_ungrab, "/_/api/ungrab",
   struct ApiPieceUngrab {
+    #[serde(default)] autoraise: bool,
   }
 
   as:
@@ -351,6 +352,45 @@ api_route!{
       gs,ioccults,player,piece,ipc,ipieces,to_recalculate, ..
     } = a;
     let gpl = gs.players.byid_mut(player).unwrap();
+
+    let new_z = if_chain! {
+
+      if self.autoraise;
+      let tgpc = gs.pieces.byid(piece)?;
+      if gs.max_z > tgpc.zlevel;
+
+      let use_region = |rpiece: PieceId, rgpc: &GPiece| if_chain!{
+        if let Some(rvis) = rgpc.fully_visible_to_everyone();
+        if let Some(ripc) = wants!( ipieces.get(rpiece), ?rpiece );
+        if let Some(rregion) = wantok!( ripc.show(rvis).abs_bbox(rgpc) );
+        then { Some(rregion) }
+        else { None }
+      };
+
+      if gs.pieces.iter().find(|&(opiece, ogpc)| {
+
+        if ogpc.zlevel < tgpc.zlevel { return false }
+
+        let cannot_overlap = if_chain! {
+          if let Some(tregion) = use_region( piece, tgpc);
+          if let Some(oregion) = use_region(opiece, ogpc);
+          if ! tregion.overlaps(&oregion);
+          then { true }
+          else { false }
+        };
+        return ! cannot_overlap;
+      })
+        .is_some();
+
+      then {
+        let z = gs.max_z.z.clone_mut().increment().map_err(
+          |e| APOE::ReportViaResponse(IE::from(e).into()))?;
+        Some(ZLevel { z, zg: gs.gen })
+      }
+      else { None }
+
+    };
+
     let gpc = gs.pieces.byid_mut(piece).unwrap();
 
     let (logents, who_by) = log_did_to_piece_whoby(
@@ -362,10 +402,16 @@ api_route!{
     if gpc.held != Some(player) { throw!(OnlineError::PieceHeld) }
     gpc.held = None;
 
+    let wrc = if let Some(zlevel) = new_z {
+      gpc.zlevel = zlevel;
+      WhatResponseToClientOp::Unpredictable
+    } else {
+      WhatResponseToClientOp::Predictable
+    };
+
     let update = PieceUpdateOp::Modify(());
-    let vanilla = (WhatResponseToClientOp::Predictable,
-                   update,
-                   logents);
+
+    let vanilla = (wrc, update, logents);
       
     if let Some(occid) = gpc.occult.passive_occid() {
       // if piece is occulted, definitely repermute its occultation
index 6c4e8be2c72b5ab876319050021b0fb0ba29d4ea..f9d9c0e3c2961ec04c7fbf226569ca1e470812ae 100644 (file)
@@ -81,6 +81,7 @@ type PieceInfo = {
   queued_moves : number,
   last_seen_moved : DOMHighResTimeStamp | null, // non-0 means halo'd
   held_us_inoccult: boolean,
+  held_us_raising: boolean,
   bbox: Rect,
   drag_delta: number,
 }
@@ -966,16 +967,19 @@ function ungrab_all() {
 
 function set_grab_us(piece: PieceId, p: PieceInfo) {
   p.held = us;
+  p.held_us_raising = false;
   p.drag_delta = 0;
   redisplay_ancillaries(piece,p);
   recompute_keybindings();
 }
 function do_ungrab(piece: PieceId, p: PieceInfo) {
+  let autoraise = p.held_us_raising;
   p.held = null;
+  p.held_us_raising = false;
   p.drag_delta = 0;
   redisplay_ancillaries(piece,p);
   recompute_keybindings();
-  api_piece(api, 'ungrab', piece,p, { });
+  api_piece(api, 'ungrab', piece,p, { autoraise });
 }
 
 function clear_halo(piece: PieceId, p: PieceInfo) {
@@ -1090,6 +1094,7 @@ function drag_mousemove(e: MouseEvent) {
       if (dragraise > 0 && ddr2 >= dragraise*dragraise) {
        dragging |= DRAGGING.RAISED;
        console.log('CHECK RAISE ', dragraise, dragraise*dragraise, ddr2);
+       p.held_us_raising = true;
        piece_set_zlevel(piece,p, (oldtop_piece) => {
          let oldtop_p = pieces[oldtop_piece]!;
          let z = wasm_bindgen.increment(oldtop_p.z);
@@ -1478,6 +1483,7 @@ function piece_modify_core(piece: PieceId, p: PieceInfo,
   p.uelem.setAttributeNS(null, "x", info.pos[0]+"");
   p.uelem.setAttributeNS(null, "y", info.pos[1]+"");
   p.held = info.held;
+  p.held_us_raising = false;
   p.pinned = info.pinned;
   p.moveable = info.moveable;
   p.angle = info.angle;