diff --git a/plugins/SkyCultureMaker/src/CMakeLists.txt b/plugins/SkyCultureMaker/src/CMakeLists.txt index eb9510d93ddb5..cbf4caec3a70d 100644 --- a/plugins/SkyCultureMaker/src/CMakeLists.txt +++ b/plugins/SkyCultureMaker/src/CMakeLists.txt @@ -41,7 +41,7 @@ SET( SkyCultureMaker_SRCS types/DrawTools.hpp types/Lines.hpp types/StarLine.hpp - types/StarPoint.hpp + types/SkyPoint.hpp types/Anchor.hpp ) diff --git a/plugins/SkyCultureMaker/src/ScmConstellation.cpp b/plugins/SkyCultureMaker/src/ScmConstellation.cpp index 570f7f7234268..b64abe391491c 100644 --- a/plugins/SkyCultureMaker/src/ScmConstellation.cpp +++ b/plugins/SkyCultureMaker/src/ScmConstellation.cpp @@ -25,10 +25,12 @@ #include #include -scm::ScmConstellation::ScmConstellation(const std::vector &coordinates, - const std::vector &stars) - : coordinates(coordinates) +scm::ScmConstellation::ScmConstellation(const QString &id, const std::vector &coordinates, + const std::vector &stars, const bool isDarkConstellation) + : id(id) + , coordinates(coordinates) , stars(stars) + , isDarkConstellation(isDarkConstellation) { QSettings *conf = StelApp::getInstance().getSettings(); constellationNameFont.setPixelSize(conf->value("viewing/constellation_font_size", 15).toInt()); @@ -40,11 +42,6 @@ scm::ScmConstellation::ScmConstellation(const std::vector & updateTextPosition(); } -void scm::ScmConstellation::setId(const QString &id) -{ - ScmConstellation::id = id; -} - QString scm::ScmConstellation::getId() const { return id; @@ -109,12 +106,12 @@ void scm::ScmConstellation::setConstellation(const std::vector & updateTextPosition(); } -const std::vector& scm::ScmConstellation::getCoordinates() const +const std::vector &scm::ScmConstellation::getCoordinates() const { return coordinates; } -const std::vector& scm::ScmConstellation::getStars() const +const std::vector &scm::ScmConstellation::getStars() const { return stars; } @@ -198,9 +195,9 @@ QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId) const // Assemble lines object QJsonArray linesArray; - if (stars.size() != 0) + if (!isDarkConstellation) { - // Stars are NOT empty + // not a dark constellation, so we can add stars for (const auto &star : stars) { linesArray.append(star.toJson()); @@ -208,7 +205,7 @@ QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId) const } else { - // Stars are empty, use the coordinates + // dark constellation, so only add coordinates for (const auto &coord : coordinates) { linesArray.append(coord.toJson()); @@ -220,7 +217,7 @@ QJsonObject scm::ScmConstellation::toJson(const QString &skyCultureId) const if (artwork.getHasArt() && !artworkPath.isEmpty()) { QFileInfo fileInfo(artworkPath); - // the '/' separator is default in all skycultures + // the '/' separator is default in all sky cultures json["image"] = artwork.toJson("illustrations/" + fileInfo.fileName()); } diff --git a/plugins/SkyCultureMaker/src/ScmConstellation.hpp b/plugins/SkyCultureMaker/src/ScmConstellation.hpp index c10529b947415..1814a0128a6c9 100644 --- a/plugins/SkyCultureMaker/src/ScmConstellation.hpp +++ b/plugins/SkyCultureMaker/src/ScmConstellation.hpp @@ -42,18 +42,12 @@ namespace scm class ScmConstellation { public: - ScmConstellation(const std::vector &coordinates, const std::vector &stars); + ScmConstellation(const QString &id, const std::vector &coordinates, + const std::vector &stars, const bool isDarkConstellation); /// The frame that is used for calculation and is drawn on. static const StelCore::FrameType drawFrame = StelCore::FrameJ2000; - /** - * @brief Sets the id of the constellation - * - * @param id id - */ - void setId(const QString &id); - /** * @brief Gets the id of the constellation * @@ -212,6 +206,13 @@ class ScmConstellation */ void show(); + /** + * @brief Returns whether the constellation is a dark constellation. + * + * @return true If the constellation is a dark constellation, false otherwise. + */ + bool getIsDarkConstellation() const { return isDarkConstellation; } + private: /// Identifier of the constellation QString id; @@ -258,6 +259,9 @@ class ScmConstellation /// Whether the constellation should be drawn or not. bool isHidden = false; + /// Indicates if the constellation is a dark constellation. + bool isDarkConstellation = false; + /** * @brief Updates the XYZname that is used for the text position. */ diff --git a/plugins/SkyCultureMaker/src/ScmDraw.cpp b/plugins/SkyCultureMaker/src/ScmDraw.cpp index d3a409796613a..1f46e010c9017 100644 --- a/plugins/SkyCultureMaker/src/ScmDraw.cpp +++ b/plugins/SkyCultureMaker/src/ScmDraw.cpp @@ -37,7 +37,11 @@ void scm::ScmDraw::setSearchMode(bool active) // search mode deactivates before the star is set by the search if (inSearchMode == true && active == false) { - selectedStarIsSearched = true; + // only allow search and find for normal constellations + if(drawingMode == DrawingMode::StarsAndDSO) + { + selectedStarIsSearched = true; + } // HACK an Ctrl + Release is not triggered if Ctrl + F is trigger it manually QKeyEvent release = QKeyEvent(QEvent::KeyRelease, Qt::Key_Control, Qt::NoModifier); @@ -123,8 +127,17 @@ bool scm::ScmDraw::segmentIntersect(const Vec2d &startA, const Vec2d &directionA scm::ScmDraw::ScmDraw() : drawState(Drawing::None) - , snapToStar(true) + , drawingMode(DrawingMode::StarsAndDSO) { + QSettings *conf = StelApp::getInstance().getSettings(); + conf->beginGroup("SkyCultureMaker"); + fixedLineColor = Vec3f(conf->value("fixedLineColor", "1.0,0.5,0.5").toString()); + fixedLineAlpha = conf->value("fixedLineAlpha", 1.0).toFloat(); + floatingLineColor = Vec3f(conf->value("floatingLineColor", "1.0,0.7,0.7").toString()); + floatingLineAlpha = conf->value("floatingLineAlpha", 0.5).toFloat(); + maxSnapRadiusInPixels = conf->value("maxSnapRadiusInPixels", 25).toUInt(); + conf->endGroup(); + std::get(currentLine).start.set(0, 0, 0); std::get(currentLine).end.set(0, 0, 0); lastEraserPos.set(std::nan("1"), std::nan("1")); @@ -146,9 +159,7 @@ void scm::ScmDraw::drawLine(StelCore *core) const StelPainter painter(core->getProjection(drawFrame)); painter.setBlending(true); painter.setLineSmooth(true); - Vec3f color = {1.f, 0.5f, 0.5f}; - bool alpha = 1.0f; - painter.setColor(color, alpha); + painter.setColor(fixedLineColor, fixedLineAlpha); for (CoordinateLine p : drawnLines.coordinates) { @@ -157,8 +168,7 @@ void scm::ScmDraw::drawLine(StelCore *core) const if (hasFlag(drawState, Drawing::hasFloatingEnd)) { - color = {1.f, 0.7f, 0.7f}; - painter.setColor(color, 0.5f); + painter.setColor(floatingLineColor, floatingLineAlpha); painter.drawGreatCircleArc(std::get(currentLine).start, std::get(currentLine).end); } @@ -191,46 +201,45 @@ void scm::ScmDraw::handleMouseClicks(class QMouseEvent *event) // Draw line if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonPress) { - StelApp &app = StelApp::getInstance(); - StelCore *core = app.getCore(); - StelProjectorP prj = core->getProjection(drawFrame); - Vec3d point; - std::optional starID; - prj->unProject(x, y, point); - - // We want to combine any near start point to an existing point so that we don't create - // duplicates. - std::optional nearest = findNearestPoint(x, y, prj); - if (nearest.has_value()) - { - point = nearest.value().coordinate; - starID = nearest.value().star; - } - else if (snapToStar) + StelApp &app = StelApp::getInstance(); + StelCore *core = app.getCore(); + + if (drawingMode == DrawingMode::StarsAndDSO) { - if (hasFlag(drawState, Drawing::hasEndExistingPoint)) - { - point = std::get(currentLine).end; - starID = std::get(currentLine).end; - } - else + StelObjectMgr &objectMgr = app.getStelObjectMgr(); + if (objectMgr.getWasSelected()) { - StelObjectMgr &objectMgr = app.getStelObjectMgr(); - - if (objectMgr.getWasSelected()) + StelObjectP stelObj = objectMgr.getLastSelectedObject(); + if ((stelObj->getType() == "Star" || stelObj->getType() == "Nebula") && + !stelObj->getID().trimmed().isEmpty()) + { + appendDrawPoint(stelObj->getJ2000EquatorialPos(core), stelObj->getID()); + qDebug() + << "SkyCultureMaker: Added star/nebula to constellation with ID" + << stelObj->getID(); + } + else if (stelObj->getID().trimmed().isEmpty()) { - StelObjectP stelObj = objectMgr.getLastSelectedObject(); - Vec3d stelPos = stelObj->getJ2000EquatorialPos(core); - point = stelPos; - if (stelObj->getType() == "Star") - { - starID = stelObj->getID(); - } + qDebug() << "SkyCultureMaker: Ignored star/nebula with empty ID"; } } } + else if (drawingMode == DrawingMode::Coordinates) + { + StelProjectorP prj = core->getProjection(drawFrame); + Vec3d point; + prj->unProject(x, y, point); - appendDrawPoint(point, starID); + // Snap to nearest point if close enough + if (auto nearest = findNearestPoint(x, y, prj); nearest.has_value()) + { + point = nearest->coordinate; + } + qDebug() << "SkyCultureMaker: Added point to constellation at" + << QString::number(point.v[0]) + "," + QString::number(point.v[1]) + "," + + QString::number(point.v[2]); + appendDrawPoint(point, std::nullopt); + } event->accept(); return; @@ -252,15 +261,16 @@ void scm::ScmDraw::handleMouseClicks(class QMouseEvent *event) } else if (activeTool == DrawTools::Eraser) { - if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonPress) - { - Vec2d currentPos(x, y); - lastEraserPos = currentPos; - } - else if (event->button() == Qt::RightButton && event->type() == QEvent::MouseButtonRelease) + if (event->button() == Qt::RightButton) { - // Reset - lastEraserPos = defaultLastEraserPos; + if (event->type() == QEvent::MouseButtonPress) + { + lastEraserPos = Vec2d(x, y); + } + else if (event->type() == QEvent::MouseButtonRelease) + { + lastEraserPos = defaultLastEraserPos; + } } } } @@ -272,47 +282,45 @@ bool scm::ScmDraw::handleMouseMoves(int x, int y, Qt::MouseButtons b) if (activeTool == DrawTools::Pen) { - if (snapToStar) + Vec3d position(0, 0, 0); + + if (drawingMode == DrawingMode::StarsAndDSO) { // this wouldve been easier with cleverFind but that is private StelObjectMgr &objectMgr = app.getStelObjectMgr(); bool found = objectMgr.findAndSelect(core, x, y); - // only keep the selection if a star was selected if (found && objectMgr.getWasSelected()) { StelObjectP stelObj = objectMgr.getLastSelectedObject(); - if (stelObj->getType() != "Star") + // only keep the selection if a star or nebula was selected + if (stelObj->getType() != "Star" && stelObj->getType() != "Nebula") { objectMgr.unSelect(); } - } - } - - if (hasFlag(drawState, (Drawing::hasStart | Drawing::hasFloatingEnd))) - { - StelProjectorP prj = core->getProjection(drawFrame); - Vec3d position; - prj->unProject(x, y, position); - if (snapToStar) - { - StelObjectMgr &objectMgr = app.getStelObjectMgr(); - if (objectMgr.getWasSelected()) + // also unselect if the id is empty or only whitespace + else if (stelObj->getID().trimmed().isEmpty()) { - StelObjectP stelObj = objectMgr.getLastSelectedObject(); - Vec3d stelPos = stelObj->getJ2000EquatorialPos(core); - std::get(currentLine).end = stelPos; + objectMgr.unSelect(); } + // snap to the star and update the line position else { - std::get(currentLine).end = position; + position = stelObj->getJ2000EquatorialPos(core); } } - else + } + + if (hasFlag(drawState, (Drawing::hasStart | Drawing::hasFloatingEnd))) + { + // no selection, compute the position from the mouse cursor + if (position == Vec3d(0, 0, 0)) { std::get(currentLine).end = position; + StelProjectorP prj = core->getProjection(drawFrame); + prj->unProject(x, y, position); } - - drawState = Drawing::hasFloatingEnd; + std::get(currentLine).end = position; + drawState = Drawing::hasFloatingEnd; } } else if (activeTool == DrawTools::Eraser) @@ -368,13 +376,6 @@ void scm::ScmDraw::handleKeys(QKeyEvent *e) { if (activeTool == DrawTools::Pen) { - if (e->key() == Qt::Key::Key_Control) - { - snapToStar = e->type() != QEvent::KeyPress; - - e->accept(); - } - if (e->key() == Qt::Key::Key_Z && e->modifiers() == Qt::Modifier::CTRL) { undoLastLine(); @@ -441,7 +442,7 @@ void scm::ScmDraw::setTool(scm::DrawTools tool) drawState = Drawing::None; } -std::optional scm::ScmDraw::findNearestPoint(int x, int y, StelProjectorP prj) const +std::optional scm::ScmDraw::findNearestPoint(int x, int y, StelProjectorP prj) const { if (drawnLines.coordinates.empty()) { @@ -487,14 +488,14 @@ std::optional scm::ScmDraw::findNearestPoint(int x, int y, StelP { if (isStartPoint) { - StarPoint point = {min->start, - drawnLines.stars.at(std::distance(drawnLines.coordinates.begin(), min)).start}; + SkyPoint point = {min->start, + drawnLines.stars.at(std::distance(drawnLines.coordinates.begin(), min)).start}; return point; } else { - StarPoint point = {min->end, - drawnLines.stars.at(std::distance(drawnLines.coordinates.begin(), min)).end}; + SkyPoint point = {min->end, + drawnLines.stars.at(std::distance(drawnLines.coordinates.begin(), min)).end}; return point; } } @@ -509,6 +510,7 @@ void scm::ScmDraw::resetDrawing() drawState = Drawing::None; lastEraserPos = defaultLastEraserPos; activeTool = DrawTools::None; + drawingMode = DrawingMode::StarsAndDSO; std::get(currentLine).start.set(0, 0, 0); std::get(currentLine).end.set(0, 0, 0); std::get(currentLine).start.reset(); diff --git a/plugins/SkyCultureMaker/src/ScmDraw.hpp b/plugins/SkyCultureMaker/src/ScmDraw.hpp index fa94724783a51..b641427ed642f 100644 --- a/plugins/SkyCultureMaker/src/ScmDraw.hpp +++ b/plugins/SkyCultureMaker/src/ScmDraw.hpp @@ -31,9 +31,10 @@ #include "types/CoordinateLine.hpp" #include "types/DrawTools.hpp" #include "types/Drawing.hpp" +#include "types/DrawingMode.hpp" #include "types/Lines.hpp" #include "types/StarLine.hpp" -#include "types/StarPoint.hpp" +#include "types/SkyPoint.hpp" #include #include #include @@ -51,14 +52,23 @@ class ScmDraw : public QObject static constexpr const char id_search_window[] = "actionShow_Search_Window_Global"; static const Vec2d defaultLastEraserPos; + /// Color of fixed drawn lines. + Vec3f fixedLineColor = Vec3f(1.0f, 0.5f, 0.5f); + /// Alpha of fixed drawn lines. + float fixedLineAlpha = 1.0f; + /// Color of floating drawn lines. + Vec3f floatingLineColor = Vec3f(1.0f, 0.7f, 0.7f); + /// Alpha of floating drawn lines. + float floatingLineAlpha = 0.5f; + /// The search radius to attach to a point on a existing line. uint32_t maxSnapRadiusInPixels = 25; /// Indicates that the startPoint has been set. Drawing drawState = Drawing::None; - /// Indicates if a line start or end will snap to the nearest star. - bool snapToStar = false; + /// The current drawing mode. + DrawingMode drawingMode = DrawingMode::StarsAndDSO; /// The current pending point. std::tuple currentLine; @@ -154,14 +164,14 @@ public slots: void handleKeys(QKeyEvent *e); /** - * @brief Finds the nearest star point to the given position. + * @brief Finds the nearest sky point to the given position. * * @param x The x viewport coordinate of the mouse. * @param y The y viewport coordinate of the mouse. * @param prj The projector to use for the calculation. - * @return std::optional The found star point if available. + * @return std::optional A point in the sky or std::nullopt if no point was found. */ - std::optional findNearestPoint(int x, int y, StelProjectorP prj) const; + std::optional findNearestPoint(int x, int y, StelProjectorP prj) const; /// Undo the last drawn line. void undoLastLine(); @@ -184,7 +194,7 @@ public slots: * @brief Loads lines into the buffer from a tuple of coordinates and stars. * */ - void loadLines(const std::vector& coordinates, const std::vector& stars); + void loadLines(const std::vector &coordinates, const std::vector &stars); /** * @brief Set the active draw tool @@ -193,6 +203,13 @@ public slots: */ void setTool(DrawTools tool); + /** + * @brief Sets the drawing mode. + * + * @param mode The drawing mode to use. + */ + void setDrawingMode(DrawingMode mode) { drawingMode = mode; } + /** * @brief Resets the currently drawn lines. */ diff --git a/plugins/SkyCultureMaker/src/ScmSkyCulture.cpp b/plugins/SkyCultureMaker/src/ScmSkyCulture.cpp index 36c0d04d548a4..7e776ab9d91d8 100644 --- a/plugins/SkyCultureMaker/src/ScmSkyCulture.cpp +++ b/plugins/SkyCultureMaker/src/ScmSkyCulture.cpp @@ -38,10 +38,10 @@ void scm::ScmSkyCulture::setFallbackToInternationalNames(bool fallback) scm::ScmConstellation &scm::ScmSkyCulture::addConstellation(const QString &id, const std::vector &coordinates, - const std::vector &stars) + const std::vector &stars, + const bool isDarkConstellation) { - scm::ScmConstellation constellationObj(coordinates, stars); - constellationObj.setId(id); + scm::ScmConstellation constellationObj(id, coordinates, stars, isDarkConstellation); constellations.push_back(std::move(constellationObj)); return constellations.back(); } @@ -70,7 +70,7 @@ std::vector *scm::ScmSkyCulture::getConstellations() QJsonObject scm::ScmSkyCulture::toJson() const { QJsonObject scJsonObj; - scJsonObj["id"] = id; + scJsonObj["id"] = id; // for some reason, the classification is inside an array, eg. ["historical"] QJsonArray classificationArray = QJsonArray::fromStringList( QStringList() << classificationTypeToString(description.classification)); @@ -108,7 +108,7 @@ bool scm::ScmSkyCulture::saveDescriptionAsMarkdown(QFile &file) QTextStream out(&file); out << "# " << desc.name << "\n\n"; - + out << "## Culture Description\n" << desc.cultureDescription << "\n\n"; out << "## Sky\n" << desc.sky << "\n\n"; diff --git a/plugins/SkyCultureMaker/src/ScmSkyCulture.hpp b/plugins/SkyCultureMaker/src/ScmSkyCulture.hpp index d40908b3a995b..4d0df71393537 100644 --- a/plugins/SkyCultureMaker/src/ScmSkyCulture.hpp +++ b/plugins/SkyCultureMaker/src/ScmSkyCulture.hpp @@ -56,7 +56,7 @@ class ScmSkyCulture /// Adds a constellation to the sky culture ScmConstellation &addConstellation(const QString &id, const std::vector &coordinates, - const std::vector &stars); + const std::vector &stars, const bool isDarkConstellation); /// Removes a constellation from the sky culture by its ID void removeConstellation(const QString &id); diff --git a/plugins/SkyCultureMaker/src/SkyCultureMaker.cpp b/plugins/SkyCultureMaker/src/SkyCultureMaker.cpp index 4bee4ee82e614..5b2c8b7281e9d 100644 --- a/plugins/SkyCultureMaker/src/SkyCultureMaker.cpp +++ b/plugins/SkyCultureMaker/src/SkyCultureMaker.cpp @@ -65,7 +65,7 @@ StelPluginInfo SkyCultureMakerStelPluginInterface::getPluginInfo() const info.authors = "Vincent Gerlach (RivinHD), Luca-Philipp Grumbach (xLPMG), Fabian Hofer (Integer-Ctrl), Richard " "Hofmann (ZeyxRew), Mher Mnatsakanyan (MherMnatsakanyan03)"; info.contact = N_("Contact us using our GitHub usernames, via an Issue or the Discussion tab in the Stellarium " - "repository."); + "repository."); info.description = N_("Plugin to draw and export sky cultures in Stellarium."); info.version = SKYCULTUREMAKER_PLUGIN_VERSION; info.license = SKYCULTUREMAKER_PLUGIN_LICENSE; @@ -89,6 +89,18 @@ SkyCultureMaker::SkyCultureMaker() scmConstellationDialog = new ScmConstellationDialog(this); scmSkyCultureExportDialog = new ScmSkyCultureExportDialog(this); scmHideOrAbortMakerDialog = new ScmHideOrAbortMakerDialog(this); + + // Settings + QSettings *conf = StelApp::getInstance().getSettings(); + conf->beginGroup("SkyCultureMaker"); + + initSetting(conf, "fixedLineColor", "1.0,0.5,0.5"); + initSetting(conf, "fixedLineAlpha", 1.0); + initSetting(conf, "floatingLineColor", "1.0,0.7,0.7"); + initSetting(conf, "floatingLineAlpha", 0.5); + initSetting(conf, "maxSnapRadiusInPixels", 25); + + conf->endGroup(); } /************************************************************************* @@ -333,9 +345,19 @@ void SkyCultureMaker::setConstellationDialogVisibility(bool b) scmConstellationDialog->setVisible(b); } + // Disable the add constellation buttons when the dialog is opened + scmSkyCultureDialog->updateAddConstellationButtons(!b); setIsLineDrawEnabled(b); } +void SkyCultureMaker::setConstellationDialogIsDarkConstellation(bool isDarkConstellation) +{ + if (scmConstellationDialog != nullptr) + { + scmConstellationDialog->setIsDarkConstellation(isDarkConstellation); + } +} + void SkyCultureMaker::setSkyCultureExportDialogVisibility(bool b) { if (b != scmSkyCultureExportDialog->visible()) @@ -500,25 +522,15 @@ void SkyCultureMaker::resetScmDialogsVisibilityState() bool SkyCultureMaker::isAnyDialogVisible() const { - if (scmSkyCultureDialog != nullptr && scmSkyCultureDialog->visible()) - { - return true; - } - if (scmConstellationDialog != nullptr && scmConstellationDialog->visible()) - { - return true; - } - if (scmSkyCultureExportDialog != nullptr && scmSkyCultureExportDialog->visible()) - { - return true; - } - if (scmHideOrAbortMakerDialog != nullptr && scmHideOrAbortMakerDialog->visible()) - { - return true; - } - if (scmStartDialog != nullptr && scmStartDialog->visible()) + const StelDialog *dialogs[] = {scmSkyCultureDialog, scmConstellationDialog, scmSkyCultureExportDialog, + scmHideOrAbortMakerDialog, scmStartDialog}; + + for (const StelDialog *dialog : dialogs) { - return true; + if (dialog != nullptr && dialog->visible()) + { + return true; + } } return false; } @@ -559,3 +571,17 @@ void SkyCultureMaker::openConstellationDialog(const QString &constellationId) qWarning() << "SkyCultureMaker: Constellation dialog is not initialized."; } } + +void SkyCultureMaker::initSetting(QSettings *conf, const QString key, const QVariant &defaultValue) +{ + if (conf == nullptr) + { + qWarning() << "SkyCultureMaker: QSettings pointer is null."; + return; + } + + if (!conf->contains(key)) + { + conf->setValue(key, defaultValue); + } +} diff --git a/plugins/SkyCultureMaker/src/SkyCultureMaker.hpp b/plugins/SkyCultureMaker/src/SkyCultureMaker.hpp index cd3dba53efb0e..bc99c2dfc7b59 100644 --- a/plugins/SkyCultureMaker/src/SkyCultureMaker.hpp +++ b/plugins/SkyCultureMaker/src/SkyCultureMaker.hpp @@ -105,6 +105,13 @@ class SkyCultureMaker : public StelModule */ void setConstellationDialogVisibility(bool b); + /** + * @brief Sets whether the constellation dialog is for a dark constellation. + * + * @param isDarkConstellation The boolean value to be set. + */ + void setConstellationDialogIsDarkConstellation(bool isDarkConstellation); + /** * @brief Shows the sky culture export dialog. * @@ -296,6 +303,14 @@ public slots: /// The artwork to temporary draw on the sky. const scm::ScmConstellationArtwork *tempArtwork = nullptr; + + /** + * @brief Initializes a setting with a default value if it does not exist. + * This does not open or close the settings group. + * @param key The key of the setting. + * @param defaultValue The default value to set if the setting does not exist. + */ + void initSetting(QSettings *conf, const QString key, const QVariant &defaultValue); }; #include "StelPluginInterface.hpp" diff --git a/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.cpp b/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.cpp index 30e0696545a64..18b6929043b06 100644 --- a/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.cpp +++ b/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.cpp @@ -25,6 +25,7 @@ #include "StelApp.hpp" #include "StelGui.hpp" #include "StelObjectMgr.hpp" +#include "types/DrawingMode.hpp" #include "ui_scmConstellationDialog.h" #include #include @@ -66,6 +67,7 @@ void ScmConstellationDialog::loadFromConstellation(scm::ScmConstellation *conste { resetDialog(); } + setIsDarkConstellation(constellation->getIsDarkConstellation()); // Save the constellation that is currently being edited constellationBeingEdited = constellation; @@ -97,6 +99,54 @@ void ScmConstellationDialog::loadFromConstellation(scm::ScmConstellation *conste updateArtwork(); } +void ScmConstellationDialog::setIsDarkConstellation(bool isDark) +{ + // make sure the dialog is initialized to avoid any ui null pointers + if (!isDialogInitialized) + { + createDialogContent(); + } + + scm::ScmDraw *draw = maker->getScmDraw(); + if (draw == nullptr) + { + qWarning() << "SkyCultureMaker: ScmConstellationDialog::setIsDarkConstellation: ScmDraw is null"; + return; + } + + // the value changed, so we should reset some data from the previous mode + if(isDarkConstellation != isDark) + { + // reset drawn lines as they are not compatible between modes + draw->resetDrawing(); + + // reset artwork as well + ui->bind_star->setEnabled(false); + imageItem->hide(); + imageItem->resetAnchors(); + maker->setTempArtwork(nullptr); + + activeTool = scm::DrawTools::None; + ui->penBtn->setChecked(false); + ui->eraserBtn->setChecked(false); + maker->setDrawTool(scm::DrawTools::None); + + isDarkConstellation = isDark; + } + + if (draw != nullptr) + { + draw->setDrawingMode(isDark ? scm::DrawingMode::Coordinates : scm::DrawingMode::StarsAndDSO); + } + + if (ui != nullptr) + { + ui->titleBar->setTitle(isDark ? q_("SCM: Dark Constellation Editor") : q_("SCM: Constellation Editor")); + ui->labelsTitle->setText(isDark ? q_("Please name your Dark Constellation") + : q_("Please name your Constellation")); + } +} + void ScmConstellationDialog::retranslate() { if (dialog) @@ -118,6 +168,8 @@ void ScmConstellationDialog::createDialogContent() ui->artwork_image->setScene(imageItem->scene()); ui->bind_star->setEnabled(false); + setIsDarkConstellation(false); + connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslate())); connect(ui->titleBar, SIGNAL(movedTo(QPoint)), this, SLOT(handleMovedTo(QPoint))); connect(ui->titleBar, &TitleBar::closeClicked, this, &ScmConstellationDialog::close); @@ -398,7 +450,7 @@ bool ScmConstellationDialog::canConstellationBeSaved() const if (!imageItem->isImageAnchored()) { ui->infoLbl->setText(q_("WARNING: Could not save: An artwork is attached, but not all " - "anchors have a star bound.")); + "anchors have a star bound.")); qDebug() << "SkyCultureMaker: Could not save: An artwork is attached, but not all " "anchors have a star bound."; return false; @@ -436,7 +488,8 @@ void ScmConstellationDialog::saveConstellation() culture->removeConstellation(constellationBeingEdited->getId()); } - scm::ScmConstellation &constellation = culture->addConstellation(id, coordinates, stars); + scm::ScmConstellation &constellation = culture->addConstellation(id, coordinates, stars, + isDarkConstellation); constellation.setEnglishName(constellationEnglishName); constellation.setNativeName(constellationNativeName); @@ -468,6 +521,7 @@ void ScmConstellationDialog::resetDialog() ui->penBtn->setChecked(false); ui->eraserBtn->setChecked(false); maker->setDrawTool(scm::DrawTools::None); + setIsDarkConstellation(false); constellationId.clear(); ui->idTE->clear(); diff --git a/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.hpp b/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.hpp index 3ddb242b9e63a..4db3db231b9c9 100644 --- a/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.hpp +++ b/plugins/SkyCultureMaker/src/gui/ScmConstellationDialog.hpp @@ -46,6 +46,7 @@ class ScmConstellationDialog : public StelDialogSeparate ScmConstellationDialog(SkyCultureMaker *maker); ~ScmConstellationDialog() override; void loadFromConstellation(scm::ScmConstellation *constellation); + void setIsDarkConstellation(bool isDarkConstellation); public slots: void retranslate() override; @@ -90,27 +91,28 @@ private slots: ScmConstellationImage *imageItem; /// Holds the last used directory QString lastUsedImageDirectory; - #if defined(Q_OS_MAC) - /// Help text on how to use the pen for Mac users. - const QString helpDrawInfoPen = "Use RightClick or Control + Click to draw a connected line.\n" - "Use Double-RightClick or Control + Double-Click to stop drawing the line.\n" - "Use Command to disable snap to stars.\n" - "Use Command + F to search and connect stars."; - /// Help text on how to use the eraser for Mac users. - const QString helpDrawInfoEraser = "Hold RightClick or Control + Click to delete the line under the cursor.\n"; - #else - /// Help text on how to use the pen for non-Mac users. - const QString helpDrawInfoPen = "Use RightClick to draw a connected line.\n" - "Use Double-RightClick to stop drawing the line.\n" - "Use CTRL to disable snap to stars.\n" - "Use CTRL + F to search and connect stars."; - /// Help text on how to use the eraser for non-Mac users. - const QString helpDrawInfoEraser = "Hold RightClick to delete the line under the cursor.\n"; - #endif - +#if defined(Q_OS_MAC) + /// Help text on how to use the pen for Mac users. + const QString helpDrawInfoPen = "Use RightClick or Control + Click to draw a connected line.\n" + "Use Double-RightClick or Control + Double-Click to stop drawing the line.\n" + "Use Command + F to search and connect stars."; + /// Help text on how to use the eraser for Mac users. + const QString helpDrawInfoEraser = "Hold RightClick or Control + Click to delete the line under the cursor.\n"; +#else + /// Help text on how to use the pen for non-Mac users. + const QString helpDrawInfoPen = "Use RightClick to draw a connected line.\n" + "Use Double-RightClick to stop drawing the line.\n" + "Use CTRL + F to search and connect stars."; + /// Help text on how to use the eraser for non-Mac users. + const QString helpDrawInfoEraser = "Hold RightClick to delete the line under the cursor.\n"; +#endif + /// The constellation that is currently being edited scm::ScmConstellation *constellationBeingEdited = nullptr; + /// Indicates whether the constellation is a dark constellation + bool isDarkConstellation = false; + /** * @brief Checks whether the current data is enough for the constellation to be saved. */ diff --git a/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.cpp b/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.cpp index b8798f15ad67d..c57a5afedcdbd 100644 --- a/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.cpp +++ b/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.cpp @@ -104,8 +104,10 @@ void ScmSkyCultureDialog::createDialogContent() ui->ExportSkyCultureBtn->setEnabled(false); ui->RemoveConstellationBtn->setEnabled(false); ui->EditConstellationBtn->setEnabled(false); + connect(ui->ExportSkyCultureBtn, &QPushButton::clicked, this, &ScmSkyCultureDialog::saveSkyCulture); - connect(ui->AddConstellationBtn, &QPushButton::clicked, this, &ScmSkyCultureDialog::constellationDialog); + connect(ui->AddConstellationBtn, &QPushButton::clicked, this, [this]() { openConstellationDialog(false); }); + connect(ui->AddDarkConstellationBtn, &QPushButton::clicked, this, [this]() { openConstellationDialog(true); }); connect(ui->EditConstellationBtn, &QPushButton::clicked, this, &ScmSkyCultureDialog::editSelectedConstellation); connect(ui->constellationsList, &QListWidget::itemSelectionChanged, this, @@ -247,9 +249,10 @@ void ScmSkyCultureDialog::removeSelectedConstellation() } } -void ScmSkyCultureDialog::constellationDialog() +void ScmSkyCultureDialog::openConstellationDialog(bool isDarkConstellation) { maker->setConstellationDialogVisibility(true); + maker->setConstellationDialogIsDarkConstellation(isDarkConstellation); } void ScmSkyCultureDialog::setIdFromName(QString &name) @@ -258,6 +261,12 @@ void ScmSkyCultureDialog::setIdFromName(QString &name) maker->getCurrentSkyCulture()->setId(id); } +void ScmSkyCultureDialog::updateAddConstellationButtons(bool enabled) +{ + ui->AddConstellationBtn->setEnabled(enabled); + ui->AddDarkConstellationBtn->setEnabled(enabled); +} + void ScmSkyCultureDialog::updateEditConstellationButton() { if (!ui->constellationsList->selectedItems().isEmpty()) diff --git a/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.hpp b/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.hpp index 46b6e783ff237..0d55aaca8e987 100644 --- a/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.hpp +++ b/plugins/SkyCultureMaker/src/gui/ScmSkyCultureDialog.hpp @@ -71,6 +71,13 @@ class ScmSkyCultureDialog : public StelDialogSeparate */ void resetDialog(); + /** + * @brief Updates the add constellation button state. + * + * @param enabled Whether the button should be enabled or disabled. + */ + void updateAddConstellationButtons(bool enabled); + public slots: void retranslate() override; void close() override; @@ -80,7 +87,7 @@ protected slots: private slots: void saveSkyCulture(); - void constellationDialog(); + void openConstellationDialog(bool isDarkConstellation); void editSelectedConstellation(); void removeSelectedConstellation(); void updateEditConstellationButton(); diff --git a/plugins/SkyCultureMaker/src/gui/scmConstellationDialog.ui b/plugins/SkyCultureMaker/src/gui/scmConstellationDialog.ui index de2c3ccfa9908..115ef70de67d6 100644 --- a/plugins/SkyCultureMaker/src/gui/scmConstellationDialog.ui +++ b/plugins/SkyCultureMaker/src/gui/scmConstellationDialog.ui @@ -128,9 +128,6 @@ - - Please name the Constellation - diff --git a/plugins/SkyCultureMaker/src/gui/scmHideOrAbortMakerDialog.ui b/plugins/SkyCultureMaker/src/gui/scmHideOrAbortMakerDialog.ui index ccb7c0bdfdf3b..64097ad7f1c0f 100644 --- a/plugins/SkyCultureMaker/src/gui/scmHideOrAbortMakerDialog.ui +++ b/plugins/SkyCultureMaker/src/gui/scmHideOrAbortMakerDialog.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 200 + 500 + 160 @@ -45,7 +45,7 @@ - QFrame::Shape::StyledPanel + QFrame::NoFrame @@ -72,10 +72,7 @@ - QFrame::Shape::StyledPanel - - - QFrame::Shadow::Raised + QFrame::NoFrame @@ -101,7 +98,7 @@ Hide the plugin to resume later or abort the process? - Qt::AlignmentFlag::AlignCenter + Qt::AlignCenter diff --git a/plugins/SkyCultureMaker/src/gui/scmSkyCultureDialog.ui b/plugins/SkyCultureMaker/src/gui/scmSkyCultureDialog.ui index a54b3430b0873..311952ea0763f 100644 --- a/plugins/SkyCultureMaker/src/gui/scmSkyCultureDialog.ui +++ b/plugins/SkyCultureMaker/src/gui/scmSkyCultureDialog.ui @@ -6,13 +6,13 @@ 0 0 - 418 - 401 + 355 + 426 - 0 + 355 0 @@ -120,13 +120,10 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -hr { height: 1px; border-width: 0; } -li.unchecked::marker { content: "\2610"; } -li.checked::marker { content: "\2612"; } -</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> +</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Segoe UI'; font-size:9pt;"><br /></p></body></html> false @@ -167,8 +164,8 @@ li.checked::marker { content: "\2612"; } - - + + @@ -178,16 +175,35 @@ li.checked::marker { content: "\2612"; } - 100 + 140 0 - Add + Add Constellation - + + + + + 0 + 0 + + + + + 140 + 0 + + + + Add Dark Constellation + + + + @@ -197,7 +213,7 @@ li.checked::marker { content: "\2612"; } - 100 + 140 0 @@ -206,7 +222,7 @@ li.checked::marker { content: "\2612"; } - + @@ -216,7 +232,7 @@ li.checked::marker { content: "\2612"; } - 100 + 140 0 @@ -299,8 +315,8 @@ li.checked::marker { content: "\2612"; } 0 0 - 395 - 1200 + 320 + 1886 @@ -708,8 +724,8 @@ li.checked::marker { content: "\2612"; } - 20 - 40 + 40 + 20 diff --git a/plugins/SkyCultureMaker/src/types/DrawingMode.hpp b/plugins/SkyCultureMaker/src/types/DrawingMode.hpp new file mode 100644 index 0000000000000..b0ef03e2d54f4 --- /dev/null +++ b/plugins/SkyCultureMaker/src/types/DrawingMode.hpp @@ -0,0 +1,41 @@ +/* + * Sky Culture Maker plug-in for Stellarium + * + * Copyright (C) 2025 Vincent Gerlach + * Copyright (C) 2025 Luca-Philipp Grumbach + * Copyright (C) 2025 Fabian Hofer + * Copyright (C) 2025 Mher Mnatsakanyan + * Copyright (C) 2025 Richard Hofmann + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCM_TYPES_DRAWINGMODE_HPP +#define SCM_TYPES_DRAWINGMODE_HPP + +namespace scm +{ +/** + * @brief Enum representing the drawing modes available in the Sky Culture Maker plugin. + * The modes determine how lines can be drawn in the constellation editor. + */ +enum class DrawingMode +{ + StarsAndDSO, + + Coordinates +}; +} // namespace scm + +#endif diff --git a/plugins/SkyCultureMaker/src/types/Lines.hpp b/plugins/SkyCultureMaker/src/types/Lines.hpp index 7c06739dc8536..f807cd30b543b 100644 --- a/plugins/SkyCultureMaker/src/types/Lines.hpp +++ b/plugins/SkyCultureMaker/src/types/Lines.hpp @@ -36,7 +36,7 @@ struct Lines //! The coordinate pairs of a line. std::vector coordinates; - //! The optional available stars too the coordinates. + //! The optional available stars to the coordinates. std::vector stars; }; } // namespace scm diff --git a/plugins/SkyCultureMaker/src/types/StarPoint.hpp b/plugins/SkyCultureMaker/src/types/SkyPoint.hpp similarity index 85% rename from plugins/SkyCultureMaker/src/types/StarPoint.hpp rename to plugins/SkyCultureMaker/src/types/SkyPoint.hpp index 8d6041bef36d4..75fc11eb5e571 100644 --- a/plugins/SkyCultureMaker/src/types/StarPoint.hpp +++ b/plugins/SkyCultureMaker/src/types/SkyPoint.hpp @@ -21,8 +21,8 @@ * along with this program. If not, see . */ -#ifndef SCM_TYPES_STAR_POINT_HPP -#define SCM_TYPES_STAR_POINT_HPP +#ifndef SCM_TYPES_SKY_POINT_HPP +#define SCM_TYPES_SKY_POINT_HPP #include "VecMath.hpp" #include @@ -30,10 +30,10 @@ namespace scm { -//! The point of a single star with coordinates. -struct StarPoint +//! A point in the sky with coordinates, optionally associated with a star ID. +struct SkyPoint { - //! The coordinate of a single point. + //! The coordinate of the point. Vec3d coordinate; //! The optional star at that coordinate. diff --git a/plugins/SkyCultureMaker/src/types/StarLine.hpp b/plugins/SkyCultureMaker/src/types/StarLine.hpp index 7a782339c551f..c26daaf5d3903 100644 --- a/plugins/SkyCultureMaker/src/types/StarLine.hpp +++ b/plugins/SkyCultureMaker/src/types/StarLine.hpp @@ -41,11 +41,13 @@ struct StarLine std::optional end; /** - * @brief Gets the star ID from the name. + * @brief Gets the formatted star Id from the name. + * + * @param starId The Id of the star or DSO, which may contain identifiers like "HIP" or "Gaia DR3". + * @return QString The formatted star Id, either as plain number for HIP or Gaia, or as "DSO:" for others. * - * @param starId The ID of the star, which may contain identifiers like "HIP" or "Gaia DR3". */ - static QString getStarIdNumber(QString starId) + static QString getFormattedStarId(QString starId) { QRegularExpression hipExpression(R"(HIP\s+(\d+))"); QRegularExpression gaiaExpression(R"(Gaia DR3\s+(\d+))"); @@ -60,7 +62,8 @@ struct StarLine { return gaiaMatch.captured(1); } - return "-1"; + // Neither HIP nor Gaia, return as DSO + return "DSO:" + starId.remove(' '); } /** @@ -74,17 +77,17 @@ struct StarLine if (start.has_value()) { - QString number = getStarIdNumber(start.value()); + QString formattedStarId = getFormattedStarId(start.value()); if (start.value().contains("HIP")) { - // HIP are required as int - json.append(number.toInt()); + // HIP are required as number + json.append(formattedStarId.toLongLong()); } else { - // Gaia is required as string - json.append(number); + // Other ids are required as string + json.append(formattedStarId); } } else @@ -94,17 +97,17 @@ struct StarLine if (end.has_value()) { - QString number = getStarIdNumber(end.value()); + QString formattedStarId = getFormattedStarId(end.value()); if (end.value().contains("HIP")) { - // HIP are required as int - json.append(number.toInt()); + // HIP are required as number + json.append(formattedStarId.toLongLong()); } else { - // Gaia is required as string - json.append(number); + // Other ids are required as string + json.append(formattedStarId); } } else