OSDN Git Service

[Feature] 画面表示関数の表示座標をずらす機能
authorHabu <habu1010+github@gmail.com>
Thu, 5 Jan 2023 15:51:50 +0000 (00:51 +0900)
committerHabu <habu1010+github@gmail.com>
Thu, 5 Jan 2023 15:51:50 +0000 (00:51 +0900)
画面表示関数の表示座標をずらす機能として、TermOffsetSetter および
TermCenteredOffsetSetter クラスを導入する。
これらのクラスはオブジェクト生成時にコンストラクタで与えられた引数を元に画面表示関数の
表示座標オフセットを変更し、オブジェクト破棄時にオブジェクト生成時に設定されていた表示
座標オフセットを復元する。

src/term/z-term.cpp
src/term/z-term.h

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) {
index 6507c20..bc6a5be 100644 (file)
@@ -13,8 +13,8 @@
 
 #include "system/angband.h"
 #include "system/h-basic.h"
-
 #include <memory>
+#include <optional>
 #include <stack>
 #include <string_view>
 #include <vector>
@@ -77,6 +77,9 @@ struct term_type {
     TERM_LEN wid{}; //!< Window Width(max 255)
     TERM_LEN hgt{}; //!< Window Height(max 255)
 
+    TERM_LEN offset_x{};
+    TERM_LEN offset_y{};
+
     TERM_LEN y1{}; //!< Minimum modified row
     TERM_LEN y2{}; //!< Maximum modified row
 
@@ -113,6 +116,34 @@ struct term_type {
     term_type &operator=(term_type &&) = default;
 };
 
+class TermOffsetSetter {
+public:
+    TermOffsetSetter(std::optional<TERM_LEN> x, std::optional<TERM_LEN> y);
+    ~TermOffsetSetter();
+    TermOffsetSetter(const TermOffsetSetter &) = delete;
+    TermOffsetSetter &operator=(const TermOffsetSetter &) = delete;
+    TermOffsetSetter(TermOffsetSetter &&) = delete;
+    TermOffsetSetter &operator=(TermOffsetSetter &&) = delete;
+
+private:
+    term_type *term;
+    TERM_LEN orig_offset_x;
+    TERM_LEN orig_offset_y;
+};
+
+class TermCenteredOffsetSetter {
+public:
+    TermCenteredOffsetSetter(std::optional<TERM_LEN> width, std::optional<TERM_LEN> height);
+    ~TermCenteredOffsetSetter() = default;
+    TermCenteredOffsetSetter(const TermCenteredOffsetSetter &) = delete;
+    TermCenteredOffsetSetter &operator=(const TermCenteredOffsetSetter &) = delete;
+    TermCenteredOffsetSetter(TermCenteredOffsetSetter &&) = delete;
+    TermCenteredOffsetSetter &operator=(TermCenteredOffsetSetter &&) = delete;
+
+private:
+    std::optional<TermOffsetSetter> tos;
+};
+
 /**** Available Constants ****/
 
 /*