mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 17:20:06 +00:00 
			
		
		
		
	Initial LinkedVectors draw item implementation
This commit is contained in:
		
							parent
							
								
									8ae973c4cb
								
							
						
					
					
						commit
						58c7b9accb
					
				
					 4 changed files with 409 additions and 0 deletions
				
			
		|  | @ -63,6 +63,7 @@ set(HDR_GL_DRAW source/scwx/qt/gl/draw/draw_item.hpp | ||||||
|                 source/scwx/qt/gl/draw/geo_icons.hpp |                 source/scwx/qt/gl/draw/geo_icons.hpp | ||||||
|                 source/scwx/qt/gl/draw/geo_lines.hpp |                 source/scwx/qt/gl/draw/geo_lines.hpp | ||||||
|                 source/scwx/qt/gl/draw/icons.hpp |                 source/scwx/qt/gl/draw/icons.hpp | ||||||
|  |                 source/scwx/qt/gl/draw/linked_vectors.hpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_icons.hpp |                 source/scwx/qt/gl/draw/placefile_icons.hpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_images.hpp |                 source/scwx/qt/gl/draw/placefile_images.hpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_lines.hpp |                 source/scwx/qt/gl/draw/placefile_lines.hpp | ||||||
|  | @ -74,6 +75,7 @@ set(SRC_GL_DRAW source/scwx/qt/gl/draw/draw_item.cpp | ||||||
|                 source/scwx/qt/gl/draw/geo_icons.cpp |                 source/scwx/qt/gl/draw/geo_icons.cpp | ||||||
|                 source/scwx/qt/gl/draw/geo_lines.cpp |                 source/scwx/qt/gl/draw/geo_lines.cpp | ||||||
|                 source/scwx/qt/gl/draw/icons.cpp |                 source/scwx/qt/gl/draw/icons.cpp | ||||||
|  |                 source/scwx/qt/gl/draw/linked_vectors.cpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_icons.cpp |                 source/scwx/qt/gl/draw/placefile_icons.cpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_images.cpp |                 source/scwx/qt/gl/draw/placefile_images.cpp | ||||||
|                 source/scwx/qt/gl/draw/placefile_lines.cpp |                 source/scwx/qt/gl/draw/placefile_lines.cpp | ||||||
|  |  | ||||||
|  | @ -123,6 +123,17 @@ GeoLines::~GeoLines() = default; | ||||||
| GeoLines::GeoLines(GeoLines&&) noexcept            = default; | GeoLines::GeoLines(GeoLines&&) noexcept            = default; | ||||||
| GeoLines& GeoLines::operator=(GeoLines&&) noexcept = default; | GeoLines& GeoLines::operator=(GeoLines&&) noexcept = default; | ||||||
| 
 | 
 | ||||||
|  | void GeoLines::set_selected_time( | ||||||
|  |    std::chrono::system_clock::time_point selectedTime) | ||||||
|  | { | ||||||
|  |    p->selectedTime_ = selectedTime; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GeoLines::set_thresholded(bool thresholded) | ||||||
|  | { | ||||||
|  |    p->thresholded_ = thresholded; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GeoLines::Initialize() | void GeoLines::Initialize() | ||||||
| { | { | ||||||
|    gl::OpenGLFunctions& gl = p->context_->gl(); |    gl::OpenGLFunctions& gl = p->context_->gl(); | ||||||
|  |  | ||||||
							
								
								
									
										249
									
								
								scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								scwx-qt/source/scwx/qt/gl/draw/linked_vectors.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,249 @@ | ||||||
|  | #include <scwx/qt/gl/draw/linked_vectors.hpp> | ||||||
|  | #include <scwx/qt/gl/draw/geo_lines.hpp> | ||||||
|  | #include <scwx/qt/util/geographic_lib.hpp> | ||||||
|  | #include <scwx/wsr88d/rpg/linked_vector_packet.hpp> | ||||||
|  | 
 | ||||||
|  | #include <boost/iterator/zip_iterator.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace gl | ||||||
|  | { | ||||||
|  | namespace draw | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | static const std::string logPrefix_ = "scwx::qt::gl::draw::linked_vectors"; | ||||||
|  | 
 | ||||||
|  | static const boost::gil::rgba32f_pixel_t kBlack {0.0f, 0.0f, 0.0f, 1.0f}; | ||||||
|  | 
 | ||||||
|  | struct LinkedVectorDrawItem | ||||||
|  | { | ||||||
|  |    LinkedVectorDrawItem( | ||||||
|  |       const common::Coordinate&                               center, | ||||||
|  |       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||||
|  |    { | ||||||
|  |       coordinates_.push_back(util::GeographicLib::GetCoordinate( | ||||||
|  |          center, vectorPacket->start_i_km(), vectorPacket->start_j_km())); | ||||||
|  | 
 | ||||||
|  |       const auto endI = vectorPacket->end_i_km(); | ||||||
|  |       const auto endJ = vectorPacket->end_j_km(); | ||||||
|  | 
 | ||||||
|  |       std::for_each( | ||||||
|  |          boost::make_zip_iterator( | ||||||
|  |             boost::make_tuple(endI.begin(), endJ.begin())), | ||||||
|  |          boost::make_zip_iterator(boost::make_tuple(endI.end(), endJ.end())), | ||||||
|  |          [this, ¢er](const auto& p) | ||||||
|  |          { | ||||||
|  |             coordinates_.push_back(util::GeographicLib::GetCoordinate( | ||||||
|  |                center, p.get<0>(), p.get<1>())); | ||||||
|  |          }); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    std::vector<std::shared_ptr<GeoLineDrawItem>> borderDrawItems_ {}; | ||||||
|  |    std::vector<std::shared_ptr<GeoLineDrawItem>> lineDrawItems_ {}; | ||||||
|  | 
 | ||||||
|  |    std::vector<common::Coordinate> coordinates_ {}; | ||||||
|  | 
 | ||||||
|  |    boost::gil::rgba32f_pixel_t modulate_ {1.0f, 1.0f, 1.0f, 1.0f}; | ||||||
|  |    float                       width_ {5.0f}; | ||||||
|  |    bool                        visible_ {true}; | ||||||
|  |    std::string                 hoverText_ {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class LinkedVectors::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl(std::shared_ptr<GlContext> context) : | ||||||
|  |        context_ {context}, geoLines_ {std::make_shared<GeoLines>(context)} | ||||||
|  |    { | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    ~Impl() {} | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<GlContext> context_; | ||||||
|  | 
 | ||||||
|  |    bool borderEnabled_ {true}; | ||||||
|  |    bool visible_ {true}; | ||||||
|  | 
 | ||||||
|  |    std::vector<std::shared_ptr<LinkedVectorDrawItem>> vectorList_ {}; | ||||||
|  |    std::shared_ptr<GeoLines>                          geoLines_; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | LinkedVectors::LinkedVectors(std::shared_ptr<GlContext> context) : | ||||||
|  |     DrawItem(context->gl()), p(std::make_unique<Impl>(context)) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | LinkedVectors::~LinkedVectors() = default; | ||||||
|  | 
 | ||||||
|  | LinkedVectors::LinkedVectors(LinkedVectors&&) noexcept            = default; | ||||||
|  | LinkedVectors& LinkedVectors::operator=(LinkedVectors&&) noexcept = default; | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::set_selected_time( | ||||||
|  |    std::chrono::system_clock::time_point selectedTime) | ||||||
|  | { | ||||||
|  |    p->geoLines_->set_selected_time(selectedTime); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::set_thresholded(bool thresholded) | ||||||
|  | { | ||||||
|  |    p->geoLines_->set_thresholded(thresholded); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::Initialize() | ||||||
|  | { | ||||||
|  |    p->geoLines_->Initialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::Render( | ||||||
|  |    const QMapLibreGL::CustomLayerRenderParameters& params) | ||||||
|  | { | ||||||
|  |    if (!p->visible_) | ||||||
|  |    { | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    p->geoLines_->Render(params); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::Deinitialize() | ||||||
|  | { | ||||||
|  |    p->geoLines_->Deinitialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetBorderEnabled(bool enabled) | ||||||
|  | { | ||||||
|  |    p->borderEnabled_ = enabled; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVisible(bool visible) | ||||||
|  | { | ||||||
|  |    p->visible_ = visible; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::StartVectors() | ||||||
|  | { | ||||||
|  |    // Start a new set of geo lines
 | ||||||
|  |    p->geoLines_->StartLines(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<LinkedVectorDrawItem> LinkedVectors::AddVector( | ||||||
|  |    const common::Coordinate&                               center, | ||||||
|  |    const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket) | ||||||
|  | { | ||||||
|  |    return p->vectorList_.emplace_back( | ||||||
|  |       std::make_shared<LinkedVectorDrawItem>(center, vectorPacket)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVectorModulate( | ||||||
|  |    const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |    boost::gil::rgba8_pixel_t                    modulate) | ||||||
|  | { | ||||||
|  |    di->modulate_ = {modulate[0] / 255.0f, | ||||||
|  |                     modulate[1] / 255.0f, | ||||||
|  |                     modulate[2] / 255.0f, | ||||||
|  |                     modulate[3] / 255.0f}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVectorModulate( | ||||||
|  |    const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |    boost::gil::rgba32f_pixel_t                  modulate) | ||||||
|  | { | ||||||
|  |    di->modulate_ = modulate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVectorWidth( | ||||||
|  |    const std::shared_ptr<LinkedVectorDrawItem>& di, float width) | ||||||
|  | { | ||||||
|  |    di->width_ = width; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVectorVisible( | ||||||
|  |    const std::shared_ptr<LinkedVectorDrawItem>& di, bool visible) | ||||||
|  | { | ||||||
|  |    di->visible_ = visible; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::SetVectorHoverText( | ||||||
|  |    const std::shared_ptr<LinkedVectorDrawItem>& di, const std::string& text) | ||||||
|  | { | ||||||
|  |    di->hoverText_ = text; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LinkedVectors::FinishVectors() | ||||||
|  | { | ||||||
|  |    // Generate borders
 | ||||||
|  |    if (p->borderEnabled_) | ||||||
|  |    { | ||||||
|  |       for (auto& di : p->vectorList_) | ||||||
|  |       { | ||||||
|  |          for (std::size_t i = 0; i < di->coordinates_.size() - 1; ++i) | ||||||
|  |          { | ||||||
|  |             auto borderLine = p->geoLines_->AddLine(); | ||||||
|  | 
 | ||||||
|  |             const double& latitude1  = di->coordinates_[i].latitude_; | ||||||
|  |             const double& longitude1 = di->coordinates_[i].longitude_; | ||||||
|  |             const double& latitude2  = di->coordinates_[i + 1].latitude_; | ||||||
|  |             const double& longitude2 = di->coordinates_[i + 1].longitude_; | ||||||
|  | 
 | ||||||
|  |             GeoLines::SetLineLocation( | ||||||
|  |                borderLine, latitude1, longitude1, latitude2, longitude2); | ||||||
|  | 
 | ||||||
|  |             GeoLines::SetLineModulate(borderLine, kBlack); | ||||||
|  |             GeoLines::SetLineWidth(borderLine, di->width_ + 2.0f); | ||||||
|  |             GeoLines::SetLineVisible(borderLine, di->visible_); | ||||||
|  | 
 | ||||||
|  |             di->borderDrawItems_.emplace_back(std::move(borderLine)); | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Generate geo lines
 | ||||||
|  |    for (auto& di : p->vectorList_) | ||||||
|  |    { | ||||||
|  |       for (std::size_t i = 0; i < di->coordinates_.size() - 1; ++i) | ||||||
|  |       { | ||||||
|  |          auto geoLine = p->geoLines_->AddLine(); | ||||||
|  | 
 | ||||||
|  |          const double& latitude1  = di->coordinates_[i].latitude_; | ||||||
|  |          const double& longitude1 = di->coordinates_[i].longitude_; | ||||||
|  |          const double& latitude2  = di->coordinates_[i + 1].latitude_; | ||||||
|  |          const double& longitude2 = di->coordinates_[i + 1].longitude_; | ||||||
|  | 
 | ||||||
|  |          GeoLines::SetLineLocation( | ||||||
|  |             geoLine, latitude1, longitude1, latitude2, longitude2); | ||||||
|  | 
 | ||||||
|  |          GeoLines::SetLineModulate(geoLine, di->modulate_); | ||||||
|  |          GeoLines::SetLineWidth(geoLine, di->width_); | ||||||
|  |          GeoLines::SetLineVisible(geoLine, di->visible_); | ||||||
|  |          GeoLines::SetLineHoverText(geoLine, di->hoverText_); | ||||||
|  | 
 | ||||||
|  |          di->lineDrawItems_.emplace_back(std::move(geoLine)); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // Finish geo lines
 | ||||||
|  |    p->geoLines_->FinishLines(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool LinkedVectors::RunMousePicking( | ||||||
|  |    const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |    const QPointF&                                  mouseLocalPos, | ||||||
|  |    const QPointF&                                  mouseGlobalPos, | ||||||
|  |    const glm::vec2&                                mouseCoords, | ||||||
|  |    const common::Coordinate&                       mouseGeoCoords, | ||||||
|  |    std::shared_ptr<types::EventHandler>&           eventHandler) | ||||||
|  | { | ||||||
|  |    return p->geoLines_->RunMousePicking(params, | ||||||
|  |                                         mouseLocalPos, | ||||||
|  |                                         mouseGlobalPos, | ||||||
|  |                                         mouseCoords, | ||||||
|  |                                         mouseGeoCoords, | ||||||
|  |                                         eventHandler); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace draw
 | ||||||
|  | } // namespace gl
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										147
									
								
								scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								scwx-qt/source/scwx/qt/gl/draw/linked_vectors.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,147 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/gl/gl_context.hpp> | ||||||
|  | #include <scwx/qt/gl/draw/draw_item.hpp> | ||||||
|  | 
 | ||||||
|  | #include <boost/gil.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace wsr88d | ||||||
|  | { | ||||||
|  | namespace rpg | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class LinkedVectorPacket; | ||||||
|  | 
 | ||||||
|  | } // namespace rpg
 | ||||||
|  | } // namespace wsr88d
 | ||||||
|  | 
 | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace gl | ||||||
|  | { | ||||||
|  | namespace draw | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | struct LinkedVectorDrawItem; | ||||||
|  | 
 | ||||||
|  | class LinkedVectors : public DrawItem | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit LinkedVectors(std::shared_ptr<GlContext> context); | ||||||
|  |    ~LinkedVectors(); | ||||||
|  | 
 | ||||||
|  |    LinkedVectors(const LinkedVectors&)            = delete; | ||||||
|  |    LinkedVectors& operator=(const LinkedVectors&) = delete; | ||||||
|  | 
 | ||||||
|  |    LinkedVectors(LinkedVectors&&) noexcept; | ||||||
|  |    LinkedVectors& operator=(LinkedVectors&&) noexcept; | ||||||
|  | 
 | ||||||
|  |    void set_selected_time(std::chrono::system_clock::time_point selectedTime); | ||||||
|  |    void set_thresholded(bool thresholded); | ||||||
|  | 
 | ||||||
|  |    void Initialize() override; | ||||||
|  |    void Render(const QMapLibreGL::CustomLayerRenderParameters& params) override; | ||||||
|  |    void Deinitialize() override; | ||||||
|  | 
 | ||||||
|  |    bool | ||||||
|  |    RunMousePicking(const QMapLibreGL::CustomLayerRenderParameters& params, | ||||||
|  |                    const QPointF&                        mouseLocalPos, | ||||||
|  |                    const QPointF&                        mouseGlobalPos, | ||||||
|  |                    const glm::vec2&                      mouseCoords, | ||||||
|  |                    const common::Coordinate&             mouseGeoCoords, | ||||||
|  |                    std::shared_ptr<types::EventHandler>& eventHandler) override; | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Enables or disables the border around each line in a linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] enabled Border visibility | ||||||
|  |     */ | ||||||
|  |    void SetBorderEnabled(bool enabled); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the visibility of the linked vectors. | ||||||
|  |     * | ||||||
|  |     * @param [in] visible Line visibility | ||||||
|  |     */ | ||||||
|  |    void SetVisible(bool visible); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Resets and prepares the draw item for adding a new set of linked vectors. | ||||||
|  |     */ | ||||||
|  |    void StartVectors(); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Adds a linked vector to the internal draw list. | ||||||
|  |     * | ||||||
|  |     * @param [in] center Center coordinate on which the linked vectors are based | ||||||
|  |     * @param [in] vectorPacket Linked vector packet containing start and end | ||||||
|  |     * points | ||||||
|  |     * | ||||||
|  |     * @return Linked vector draw item | ||||||
|  |     */ | ||||||
|  |    std::shared_ptr<LinkedVectorDrawItem> AddVector( | ||||||
|  |       const common::Coordinate&                               center, | ||||||
|  |       const std::shared_ptr<wsr88d::rpg::LinkedVectorPacket>& vectorPacket); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the modulate color of a linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] di Linked vector draw item | ||||||
|  |     * @param [in] modulate Modulate color | ||||||
|  |     */ | ||||||
|  |    static void | ||||||
|  |    SetVectorModulate(const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |                      boost::gil::rgba8_pixel_t                    color); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the modulate color of a linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] di Linked vector draw item | ||||||
|  |     * @param [in] modulate Modulate color | ||||||
|  |     */ | ||||||
|  |    static void | ||||||
|  |    SetVectorModulate(const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |                      boost::gil::rgba32f_pixel_t                  modulate); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the width of the linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] width Width in pixels | ||||||
|  |     */ | ||||||
|  |    static void SetVectorWidth(const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |                               float width); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the visibility of the linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] visible | ||||||
|  |     */ | ||||||
|  |    static void SetVectorVisible(const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |                                 bool visible); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Sets the hover text of a linked vector. | ||||||
|  |     * | ||||||
|  |     * @param [in] di Linked vector draw item | ||||||
|  |     * @param [in] text Hover text | ||||||
|  |     */ | ||||||
|  |    static void | ||||||
|  |    SetVectorHoverText(const std::shared_ptr<LinkedVectorDrawItem>& di, | ||||||
|  |                       const std::string&                           text); | ||||||
|  | 
 | ||||||
|  |    /**
 | ||||||
|  |     * Finalizes the draw item after adding new linked vectors. | ||||||
|  |     */ | ||||||
|  |    void FinishVectors(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace draw
 | ||||||
|  | } // namespace gl
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat