OSDN Git Service

[Feature] 画面表示関数の表示座標をずらす機能
[hengbandforosx/hengbandosx.git] / src / term / z-term.cpp
index 4d0d387..fdff5d6 100644 (file)
@@ -35,6 +35,64 @@ term_type *game_term = nullptr;
 
 /*** Local routines ***/
 
+/*!
+ * @brief オブジェクトが生存している間、画面表示関数の座標をずらす。
+ *
+ * 引数でずらすX座標オフセット、Y座標オフセットをそれぞれ指定する。
+ * 正方向のオフセットのみ有効。負の値が指定された場合、オフセット位置は 0 とする。
+ * 指定された座標が std::nullopt の場合、現在のオフセットを維持する。
+ *
+ * @param x X座標オフセット
+ * @param y Y座標オフセット
+ */
+TermOffsetSetter::TermOffsetSetter(std::optional<TERM_LEN> x, std::optional<TERM_LEN> y)
+    : term(game_term)
+    , orig_offset_x(game_term != nullptr ? game_term->offset_x : 0)
+    , orig_offset_y(game_term != nullptr ? game_term->offset_y : 0)
+{
+    if (this->term == nullptr) {
+        return;
+    }
+
+    if (x.has_value()) {
+        this->term->offset_x = (x.value() > 0) ? x.value() : 0;
+    }
+    if (y.has_value()) {
+        this->term->offset_y = (y.value() > 0) ? y.value() : 0;
+    }
+}
+
+TermOffsetSetter::~TermOffsetSetter()
+{
+    if (this->term == nullptr) {
+        return;
+    }
+
+    this->term->offset_x = this->orig_offset_x;
+    this->term->offset_y = this->orig_offset_y;
+}
+
+/*!
+ * @brief オブジェクトが生存している間、画面表示関数の座標をずらす。
+ *
+ * 表示に使用する領域の大きさを指定し、その領域が画面中央に表示されるように座標をずらす。
+ * 引数で領域の横幅、縦幅をそれぞれ指定する。
+ * 画面の幅より大きな値が指定された場合はオフセット 0 になる。
+ * 指定された幅が std::nullopt の場合、画面の幅全体を使用する(オフセット 0 になる)。
+ *
+ * @param width 表示に使用する領域の横幅
+ * @param height 表示に使用する領域の縦幅
+ */
+TermCenteredOffsetSetter::TermCenteredOffsetSetter(std::optional<TERM_LEN> width, std::optional<TERM_LEN> height)
+{
+    TERM_LEN term_width, term_height;
+    term_get_size(&term_width, &term_height);
+
+    const auto offset_x = width.has_value() ? (term_width - width.value()) / 2 : 0;
+    const auto offset_y = height.has_value() ? (term_height - height.value()) / 2 : 0;
+    this->tos.emplace(offset_x, offset_y);
+}
+
 /*
  * Initialize a "term_win" (using the given window size)
  */
@@ -194,7 +252,7 @@ static errr term_pict_hack(TERM_LEN x, TERM_LEN y, int n, const TERM_COLOR *ap,
  * Mentally draw an attr/char at a given location
  * Assumes given location and values are valid.
  */
-void term_queue_char(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR ta, char tc)
+static void term_queue_char_aux(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR ta, char tc)
 {
     const auto &scrn = game_term->scr;
 
@@ -242,6 +300,15 @@ void term_queue_char(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR ta
         }
 }
 
+void term_queue_char(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR ta, char tc)
+{
+    if (auto res = term_gotoxy(x, y); res != 0) {
+        return;
+    }
+
+    term_queue_char_aux(game_term->scr->cx, game_term->scr->cy, a, c, ta, tc);
+}
+
 /*
  * Bigtile version of term_queue_char().
  * If use_bigtile is FALSE, simply call term_queue_char().
@@ -268,9 +335,13 @@ void term_queue_bigchar(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR
     byte a2;
     char c2;
 
+    if (auto res = term_gotoxy(x, y); res != 0) {
+        return;
+    }
+
     /* If non bigtile mode, call orginal function */
     if (!use_bigtile) {
-        term_queue_char(x, y, a, c, ta, tc);
+        term_queue_char_aux(game_term->scr->cx, game_term->scr->cy, a, c, ta, tc);
         return;
     }
 
@@ -311,8 +382,8 @@ void term_queue_bigchar(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c, TERM_COLOR
     }
 
     /* Display pair of attr/char */
-    term_queue_char(x, y, a, c, ta, tc);
-    term_queue_char(x + 1, y, a2, c2, 0, 0);
+    term_queue_char_aux(game_term->scr->cx, game_term->scr->cy, a, c, ta, tc);
+    term_queue_char_aux(game_term->scr->cx + 1, game_term->scr->cy, a2, c2, 0, 0);
 }
 
 /*
@@ -1288,6 +1359,9 @@ errr term_gotoxy(TERM_LEN x, TERM_LEN y)
     int w = game_term->wid;
     int h = game_term->hgt;
 
+    x += game_term->offset_x;
+    y += game_term->offset_y;
+
     /* Verify */
     if ((x < 0) || (x >= w)) {
         return -1;
@@ -1312,13 +1386,7 @@ errr term_gotoxy(TERM_LEN x, TERM_LEN y)
  */
 errr term_draw(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c)
 {
-    int w = game_term->wid;
-    int h = game_term->hgt;
-
-    if ((x < 0) || (x >= w)) {
-        return -1;
-    }
-    if ((y < 0) || (y >= h)) {
+    if (auto res = term_gotoxy(x, y); res != 0) {
         return -1;
     }
 
@@ -1328,7 +1396,7 @@ errr term_draw(TERM_LEN x, TERM_LEN y, TERM_COLOR a, char c)
     }
 
     /* Queue it for later */
-    term_queue_char(x, y, a, c, 0, 0);
+    term_queue_char_aux(game_term->scr->cx, game_term->scr->cy, a, c, 0, 0);
     return 0;
 }
 
@@ -1363,7 +1431,7 @@ errr term_addch(TERM_COLOR a, char c)
     }
 
     /* Queue the given character for display */
-    term_queue_char(game_term->scr->cx, game_term->scr->cy, a, c, 0, 0);
+    term_queue_char_aux(game_term->scr->cx, game_term->scr->cy, a, c, 0, 0);
 
     /* Advance the cursor */
     game_term->scr->cx++;
@@ -1535,6 +1603,9 @@ errr term_erase(TERM_LEN x, TERM_LEN y, int n)
         return -1;
     }
 
+    x = game_term->scr->cx;
+    y = game_term->scr->cy;
+
     /* Force legal size */
     if (x + n > w) {
         n = w - x;
@@ -1780,8 +1851,8 @@ errr term_get_size(TERM_LEN *w, TERM_LEN *h)
 errr term_locate(TERM_LEN *x, TERM_LEN *y)
 {
     /* Access the cursor */
-    (*x) = game_term->scr->cx;
-    (*y) = game_term->scr->cy;
+    *x = game_term->scr->cx - game_term->offset_x;
+    *y = game_term->scr->cy - game_term->offset_y;
 
     /* Warn about "useless" cursor */
     if (game_term->scr->cu) {