diff --git a/src/celestia/celestiacore.cpp b/src/celestia/celestiacore.cpp index 0bd91ebba..fcd4b407b 100644 --- a/src/celestia/celestiacore.cpp +++ b/src/celestia/celestiacore.cpp @@ -2221,7 +2221,17 @@ int CelestiaCore::getSafeAreaHeight() const void CelestiaCore::setSafeAreaInsets(int left, int top, int right, int bottom) { - safeAreaInsets = { left, top, right, bottom }; + setSafeAreaInsets({ left, top, right, bottom }); +} + +void CelestiaCore::setSafeAreaInsets(const CelestiaCore::EdgeInsets& insets) +{ + safeAreaInsets = insets; +} + +CelestiaCore::EdgeInsets CelestiaCore::getSafeAreaInsets() const +{ + return safeAreaInsets; } float CelestiaCore::getPickTolerance() const @@ -2458,11 +2468,84 @@ void CelestiaCore::showText(const std::string &s, if (!shouldShowText) return; + class RelativeTextPrintPosition: public TextPrintPosition + { + public: + RelativeTextPrintPosition(int messageHOrigin, + int messageVOrigin, + int messageHOffset, + int messageVOffset) : + TextPrintPosition(), + messageHOrigin(messageHOrigin), + messageVOrigin(messageVOrigin), + messageHOffset(messageHOffset), + messageVOffset(messageVOffset) + { + }; + + ~RelativeTextPrintPosition() override = default; + + void resolvePixelPosition(CelestiaCore* appCore, int& x, int& y) override + { + auto font = appCore->titleFont; + int emWidth = font->getWidth("M"); + int fontHeight = font->getHeight(); + + x = messageHOffset * emWidth; + y = messageVOffset * fontHeight; + + if (messageHOrigin == 0) + x += appCore->getSafeAreaWidth() / 2; + else if (messageHOrigin > 0) + x += appCore->getSafeAreaWidth(); + if (messageVOrigin == 0) + y += appCore->getSafeAreaHeight() / 2; + else if (messageVOrigin > 0) + y += appCore->getSafeAreaHeight(); + else if (messageVOrigin < 0) + y -= fontHeight; + + x += appCore->safeAreaInsets.left; + y += appCore->safeAreaInsets.top; + } + private: + int messageHOrigin; + int messageVOrigin; + int messageHOffset; + int messageVOffset; + + friend class CelestiaCore; + }; + messageText = s; - messageHOrigin = horig; - messageVOrigin = vorig; - messageHOffset = hoff; - messageVOffset = voff; + messageTextPosition = std::make_unique(horig, vorig, hoff, voff); + messageStart = currentTime; + messageDuration = duration; +} + +void CelestiaCore::showTextAtPixel(const std::string &s, int x, int y, double duration) +{ + class AbsoluteTextPrintPosition: public TextPrintPosition + { + public: + AbsoluteTextPrintPosition(int x, int y) : TextPrintPosition(), x(x), y(y) + { + }; + + ~AbsoluteTextPrintPosition() override = default; + + void resolvePixelPosition(CelestiaCore*, int& x, int& y) override + { + x = this->x; + y = this->y; + } + private: + int x; + int y; + }; + + messageText = s; + messageTextPosition = std::make_unique(x, y); messageStart = currentTime; messageDuration = duration; } @@ -3506,23 +3589,12 @@ void CelestiaCore::renderOverlay() } // Text messages - if (messageText != "" && currentTime < messageStart + messageDuration) + if (messageText != "" && currentTime < messageStart + messageDuration && messageTextPosition) { - int emWidth = titleFont->getWidth("M"); - int fontHeight = titleFont->getHeight(); - int x = messageHOffset * emWidth; - int y = messageVOffset * fontHeight; + int x = 0; + int y = 0; - if (messageHOrigin == 0) - x += getSafeAreaWidth() / 2; - else if (messageHOrigin > 0) - x += getSafeAreaWidth(); - if (messageVOrigin == 0) - y += getSafeAreaHeight() / 2; - else if (messageVOrigin > 0) - y += getSafeAreaHeight(); - else if (messageVOrigin < 0) - y -= fontHeight; + messageTextPosition->resolvePixelPosition(this, x, y); overlay->setFont(titleFont); overlay->savePos(); @@ -3531,7 +3603,7 @@ void CelestiaCore::renderOverlay() if (currentTime > messageStart + messageDuration - 0.5) alpha = (float) ((messageStart + messageDuration - currentTime) / 0.5); overlay->setColor(textColor.red(), textColor.green(), textColor.blue(), alpha); - overlay->moveBy(safeAreaInsets.left + x, safeAreaInsets.bottom + y); + overlay->moveBy(x, y); overlay->beginText(); *overlay << messageText; overlay->endText(); diff --git a/src/celestia/celestiacore.h b/src/celestia/celestiacore.h index 0e1b64d24..fcd6e0989 100644 --- a/src/celestia/celestiacore.h +++ b/src/celestia/celestiacore.h @@ -194,6 +194,14 @@ class CelestiaCore // : public Watchable Fahrenheit = 2, }; + struct EdgeInsets + { + int left; + int top; + int right; + int bottom; + }; + public: CelestiaCore(); ~CelestiaCore(); @@ -241,6 +249,9 @@ class CelestiaCore // : public Watchable int horig = 0, int vorig = 0, int hoff = 0, int voff = 0, double duration = 1.0e9); + void showTextAtPixel(const std::string &s, + int x = 0, int y = 0, + double duration = 1.0e9); int getTextWidth(const std::string &s) const; void readFavoritesFile(); @@ -307,6 +318,8 @@ class CelestiaCore // : public Watchable int getDistanceToScreen() const; void setDistanceToScreen(int); void setSafeAreaInsets(int left, int top, int right, int bottom); + void setSafeAreaInsets(const EdgeInsets&); + EdgeInsets getSafeAreaInsets() const; float getPickTolerance() const; void setPickTolerance(float); @@ -422,11 +435,15 @@ class CelestiaCore // : public Watchable std::shared_ptr font{ nullptr }; std::shared_ptr titleFont{ nullptr }; + class TextPrintPosition + { + public: + virtual void resolvePixelPosition(CelestiaCore* appCore, int& x, int& y) = 0; + virtual ~TextPrintPosition() = default; + }; + std::string messageText; - int messageHOrigin{ 0 }; - int messageVOrigin{ 0 }; - int messageHOffset{ 0 }; - int messageVOffset{ 0 }; + std::unique_ptr messageTextPosition; double messageStart{ 0.0 }; double messageDuration{ 0.0 }; Color textColor{ 1.0f, 1.0f, 1.0f }; @@ -526,14 +543,6 @@ class CelestiaCore // : public Watchable std::unique_ptr viewportEffect { nullptr }; bool isViewportEffectUsed { false }; - struct EdgeInsets - { - int left; - int top; - int right; - int bottom; - }; - EdgeInsets safeAreaInsets { 0, 0, 0, 0 }; MeasurementSystem measurement { Metric }; diff --git a/src/celscript/lua/celx_celestia.cpp b/src/celscript/lua/celx_celestia.cpp index 53627ff77..9c056cb10 100644 --- a/src/celscript/lua/celx_celestia.cpp +++ b/src/celscript/lua/celx_celestia.cpp @@ -128,6 +128,24 @@ static int celestia_print(lua_State* l) return 0; } +static int celestia_printatpixel(lua_State* l) +{ + Celx_CheckArgs(l, 2, 5, "One to four arguments expected to function celestia:printatpixel"); + + CelestiaCore* appCore = this_celestia(l); + const char* s = Celx_SafeGetString(l, 2, AllErrors, "First argument to celestia:print must be a string"); + double duration = Celx_SafeGetNumber(l, 3, WrongType, "Second argument to celestia:print must be a number", 1.5); + int x = (int)Celx_SafeGetNumber(l, 4, WrongType, "Third argument to celestia:print must be a number", 0.0); + int y = (int)Celx_SafeGetNumber(l, 5, WrongType, "Fourth argument to celestia:print must be a number", 0.0); + + if (duration < 0.0) + duration = 1.5; + + appCore->showTextAtPixel(s, x, y, duration); + + return 0; +} + static int celestia_gettextwidth(lua_State* l) { Celx_CheckArgs(l, 2, 2, "One argument expected to function celestia:gettextwidth"); @@ -140,6 +158,28 @@ static int celestia_gettextwidth(lua_State* l) return 1; } +static int celestia_getscreendpi(lua_State* l) +{ + Celx_CheckArgs(l, 1, 1, "No arguments expected for celestia:getscreendp()"); + + CelestiaCore* appCore = this_celestia(l); + lua_pushnumber(l, appCore->getScreenDpi()); + + return 1; +} + +static int celestia_setscreendpi(lua_State* l) +{ + Celx_CheckArgs(l, 2, 2, "One argument expected for celestia:setscreendpi()"); + int screenDpi = (int)Celx_SafeGetNumber(l, 2, AllErrors, "Argument to celestia:setscreendpi() must be a number"); + screenDpi = max(screenDpi, 1); + + CelestiaCore* appCore = this_celestia(l); + appCore->setScreenDpi(screenDpi); + + return 0; +} + static int celestia_getaltazimuthmode(lua_State* l) { Celx_CheckArgs(l, 1, 1, "No arguments expected for celestia:getaltazimuthmode()"); @@ -310,6 +350,34 @@ int celestia_getscreendimension(lua_State* l) return 2; } +int celestia_getsafeareainsets(lua_State* l) +{ + Celx_CheckArgs(l, 1, 1, "No arguments expected for celestia:getsafeareainsets()"); + // error checking only: + this_celestia(l); + CelestiaCore* appCore = to_celestia(l, 1); + const auto &edgeInsets = appCore->getSafeAreaInsets(); + lua_pushnumber(l, edgeInsets.left); + lua_pushnumber(l, edgeInsets.top); + lua_pushnumber(l, edgeInsets.right); + lua_pushnumber(l, edgeInsets.bottom); + return 4; +} + +int celestia_setsafeareainsets(lua_State* l) +{ + Celx_CheckArgs(l, 5, 5, "Four arguments expected for celestia:setsafeareainsets()"); + + CelestiaCore* appCore = getAppCore(l, AllErrors); + + int left = (int)Celx_SafeGetNumber(l, 2, WrongType, "First argument to celestia:setsafeareainsets() must be a number", 0.0); + int top = (int)Celx_SafeGetNumber(l, 3, WrongType, "Second argument to celestia:setsafeareainsets() must be a number", 0.0); + int right = (int)Celx_SafeGetNumber(l, 4, WrongType, "Third argument to celestia:setsafeareainsets() must be a number", 0.0); + int bottom = (int)Celx_SafeGetNumber(l, 5, WrongType, "Fourth argument to celestia:setsafeareainsets() must be a number", 0.0); + appCore->setSafeAreaInsets(left, top, right, bottom); + return 0; +} + static int celestia_showlabel(lua_State* l) { Celx_CheckArgs(l, 1, 1000, "Bad method call!"); @@ -2150,14 +2218,19 @@ void CreateCelestiaMetaTable(lua_State* l) Celx_RegisterMethod(l, "__tostring", celestia_tostring); Celx_RegisterMethod(l, "flash", celestia_flash); Celx_RegisterMethod(l, "print", celestia_print); + Celx_RegisterMethod(l, "printatpixel", celestia_printatpixel); Celx_RegisterMethod(l, "gettextwidth", celestia_gettextwidth); Celx_RegisterMethod(l, "show", celestia_show); Celx_RegisterMethod(l, "setaltazimuthmode", celestia_setaltazimuthmode); Celx_RegisterMethod(l, "getaltazimuthmode", celestia_getaltazimuthmode); + Celx_RegisterMethod(l, "getscreendpi", celestia_getscreendpi); + Celx_RegisterMethod(l, "setscreendpi", celestia_setscreendpi); Celx_RegisterMethod(l, "hide", celestia_hide); Celx_RegisterMethod(l, "getrenderflags", celestia_getrenderflags); Celx_RegisterMethod(l, "setrenderflags", celestia_setrenderflags); Celx_RegisterMethod(l, "getscreendimension", celestia_getscreendimension); + Celx_RegisterMethod(l, "getsafeareainsets", celestia_getsafeareainsets); + Celx_RegisterMethod(l, "setsafeareainsets", celestia_setsafeareainsets); Celx_RegisterMethod(l, "showlabel", celestia_showlabel); Celx_RegisterMethod(l, "hidelabel", celestia_hidelabel); Celx_RegisterMethod(l, "getlabelflags", celestia_getlabelflags);