chiark / gitweb /
represent and display angles
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 5 Jan 2021 01:12:02 +0000 (01:12 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 5 Jan 2021 01:12:02 +0000 (01:12 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
daemon/session.rs
specs/demo.game.toml
src/bin/otter.rs
src/gamestate.rs
src/spec.rs
templates/macros.tera

index 09af0f6cfecfb3405b5ccf3e97b4c42b9676eafe..582f22116b0c2eb84f5deab2d3f5ef331bbc46d9 100644 (file)
@@ -576,7 +576,7 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
        Fine, ig)
     },
 
-    AddPieces(PiecesSpec{ pos,posd,count,face,pinned,info }) => {
+    AddPieces(PiecesSpec{ pos,posd,count,face,pinned,angle,info }) => {
       let (ig_g, modperm, _) = cs.check_acl_modify_pieces(ag, ig)?;
       let ig = &mut **ig_g;
       let gs = &mut ig.gs;
@@ -615,6 +615,7 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
           lastclient: Default::default(),
           gen_before_lastclient: Generation(0),
           pinned: pinned.unwrap_or(false),
+          angle,
           gen: gs.gen,
           pos, face,
         };
index e52bf99ac5fbfde7c08bff803333aabdc424e899..37ef11fffbfb1246a049ab9bb83030b68239bc79 100644 (file)
@@ -31,6 +31,7 @@ struct SessionFormattedLogEntry {
 struct SessionPieceContext {
   id: VisiblePieceId,
   pos: Pos,
+  transform: VisibleAngleTransform,
   info: String, // SessionPieceLoadJson as JSON
 }
 
@@ -110,6 +111,7 @@ fn session_inner(form : Json<SessionForm>,
       else { continue /* was deleted */ };
       let defs = p.make_defs(&pri)?;
       alldefs.push((pri.id, defs));
+      let transform = make_angle_visible(pr.angle, pr.pos);
 
       let for_info = SessionPieceLoadJson {
         held : &pr.held,
@@ -120,9 +122,10 @@ fn session_inner(form : Json<SessionForm>,
       };
 
       let for_piece = SessionPieceContext {
+        transform,
         id: pri.id,
-        pos : pr.pos,
-        info : serde_json::to_string(&for_info)
+        pos: pr.pos,
+        info: serde_json::to_string(&for_info)
           .map_err(|e| InternalError::JSONEncode(e))?,
       };
       uses.push(for_piece);
index dd5bfe192ad65d29854a884ebb126719430d2572..64b7cbd6962e94539a7ce015f72db79100054c19 100644 (file)
@@ -25,5 +25,6 @@ item = "chess-w-B"
 [[pieces]]
 pos = [160,40]
 type = "Lib"
+angle.Compass = 1
 lib = "wikimedia"
 item = "chess-b-N"
index a9a5f1f555f0a05ee5d19c26c29c151d0741224a..5ba2951b2f8579fd01dbcec9bb48fb859a938196 100644 (file)
@@ -1194,6 +1194,7 @@ mod library_add {
         count: Some(to_add as u32),
         face: None,
         pinned: Some(false),
+        angle: default(),
         info: Box::new(spec),
       };
       Poor(vec![ MGI::AddPieces(spec) ],
@@ -1346,7 +1347,7 @@ mod library_add {
       let spec = PiecesSpec {
         pos: Some(pos),
         posd: None, count: Some(1), face: None, pinned: Some(false),
-        info: Box::new(spec),
+        angle: default(), info: Box::new(spec),
       };
       let insn = MGI::AddPieces(spec);
       insns.push(insn);
index 7ac57e15bcaa01fefeed3d870ddc443213fb24bf..d68be53e3cb8109c2b57d34466967442f2147300 100644 (file)
@@ -23,6 +23,11 @@ pub struct Generation(pub u64);
 
 visible_slotmap_key!{ VisiblePieceId('.') }
 
+#[derive(Clone,Debug)]
+#[derive(Serialize,Deserialize)]
+#[serde(transparent)]
+pub struct VisibleAngleTransform(String);
+
 #[derive(Clone,Serialize,Deserialize,Hash,Eq,Ord,PartialEq,PartialOrd)]
 #[serde(transparent)]
 pub struct Html(pub String);
@@ -67,6 +72,7 @@ pub struct PieceState {
   pub held: Option<PlayerId>,
   pub zlevel: ZLevel,
   pub pinned: bool,
+  #[serde(default)] pub angle: PieceAngle,
   pub gen: Generation,
   pub lastclient: ClientId,
   pub gen_before_lastclient: Generation,
@@ -321,3 +327,9 @@ pub fn make_pieceid_visible(p: PieceId) -> VisiblePieceId {
   let kd: slotmap::KeyData = p.into();
   VisiblePieceId(kd)
 }
+
+pub fn make_angle_visible(angle: PieceAngle, pos: Pos)
+                          -> VisibleAngleTransform {
+  // todo-lens need to do censorship mapping here
+  VisibleAngleTransform(angle.to_transform(pos))
+}
index 5b33af9b5d36432c53c519cd3794120eeefe5511..23712b370a80ef81f42baf1bca209fdb05d3ab7e 100644 (file)
@@ -72,6 +72,7 @@ pub enum SpecError {
   InconsistentPieceCount,
   BadUrlSyntax,
   UrlTooLong,
+  CompassAngleInvalid,
 }
 display_as_debug!{SpecError}
 
@@ -168,10 +169,23 @@ pub struct PiecesSpec {
   pub count: Option<u32>,
   pub face: Option<FaceId>,
   pub pinned: Option<bool>,
+  #[serde(default)] pub angle: PieceAngle,
   #[serde(flatten)]
   pub info: Box<dyn PieceSpec>,
 }
 
+#[derive(Debug,Copy,Clone,Serialize,Deserialize)]
+pub enum PieceAngle {
+  Compass(CompassAngle),
+}
+
+#[derive(Debug,Copy,Clone,Eq,PartialEq)]
+#[derive(Default,Serialize,Deserialize)]
+#[serde(try_from="u8")]
+#[serde(into="u8")]
+/// 0 = unrotated, +ve is anticlockwise, units of 45deg
+pub struct CompassAngle(u8);
+
 //---------- Piece specs ----------
 // the implementations are in pieces.rs
 
@@ -282,6 +296,38 @@ pub mod implementation {
   type SE = SpecError;
   type TPS = TablePlayerSpec;
 
+  impl Default for PieceAngle {
+    fn default() -> Self { PieceAngle::Compass(default()) }
+  }
+
+  impl TryFrom<u8> for CompassAngle {
+    type Error = SpecError;
+    #[throws(SpecError)]
+    fn try_from(v: u8) -> Self {
+      if v < 8 { Self(v) }
+      else { throw!(SE::CompassAngleInvalid) }
+    }
+  }
+
+  impl From<CompassAngle> for u8 {
+    fn from(a: CompassAngle) -> u8 {
+      a.0
+    }
+  }
+
+  impl PieceAngle {
+    pub fn to_transform(self, pos: Pos) -> String {
+      match self {
+        PieceAngle::Compass(CompassAngle(angle)) => {
+          if angle == 0 { default() }
+          else { format!("rotate({}, {}, {})",
+                         -45 * (angle as i16),
+                         pos.0[0], pos.0[1]) }
+        }
+      }
+    }
+  }
+
   impl<P: Eq + Hash> Default for Acl<P> {
     fn default() -> Self { Acl { ents: default() } }
   }
index 48dfa885faa199e226ab84f0dfe941d0dd69be73..32f8eac50d9105eb6d1377352a77bdbbfabba7ca 100644 (file)
@@ -61,6 +61,7 @@ Hi {{nick | escape}}
 {%- for piece in uses %}
       <use id="use{{ piece.id }}" href="#piece{{ piece.id }}"
           x="{{ piece.pos[0] }}" y="{{ piece.pos[1] }}"
+           transform="{{ piece.transform }}"
           data-piece="{{ piece.id }}" data-info="{{ piece.info | escape }}" />
 {%- endfor %}
       <g id="defs_marker"></g>