diff --git a/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp b/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp index 7bc3ecbca..335ab8281 100644 --- a/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp +++ b/android/src/main/cpp/graphics/objects/PolygonPatternGroup2dOpenGl.cpp @@ -166,6 +166,11 @@ void PolygonPatternGroup2dOpenGl::render(const std::shared_ptr<::RenderingContex auto scalingFactorHandle = glGetUniformLocation(program, "uScalingFactor"); glUniform2f(scalingFactorHandle, scalingFactor.x, scalingFactor.y); + auto screenPixelAsRealMeterFactorHandle = glGetUniformLocation(program, "uScreenPixelAsRealMeterFactor"); + if (screenPixelAsRealMeterFactorHandle >= 0) { + glUniform1f(screenPixelAsRealMeterFactorHandle, screenPixelAsRealMeterFactor); + } + int textureCoordinatesHandle = glGetUniformLocation(program, "textureCoordinates"); glUniform1fv(textureCoordinatesHandle, sizeTextureCoordinatesValuesArray, &textureCoordinates[0]); int opacitiesHandle = glGetUniformLocation(program, "opacities"); diff --git a/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.cpp b/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.cpp index f5dcf072f..3c4a7dcdb 100644 --- a/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.cpp +++ b/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.cpp @@ -12,7 +12,13 @@ #include "OpenGlContext.h" #include "OpenGlHelper.h" -const std::string PolygonPatternGroup2dShaderOpenGl::programName = "UBMAP_PolygonPatternGroup2dShaderOpenGl"; +#include +#include +#include + +PolygonPatternGroup2dShaderOpenGl::PolygonPatternGroup2dShaderOpenGl(bool fadeInPattern) + : fadeInPattern(fadeInPattern), + programName(std::string("UBMAP_PolygonPatternGroup2dShaderOpenGl_") + (fadeInPattern ? "std" : "fade")) {} std::string PolygonPatternGroup2dShaderOpenGl::getProgramName() { return programName; } @@ -45,14 +51,22 @@ std::string PolygonPatternGroup2dShaderOpenGl::getVertexShader() { uniform mat4 uMVPMatrix; uniform vec2 uScalingFactor; + ) + (fadeInPattern ? OMMShaderCode(uniform float uScreenPixelAsRealMeterFactor;) : "") + + OMMShaderCode( out vec2 pixelPosition; out flat uint styleIndex; void main() { - pixelPosition = vPosition.xy * vec2(1.0 / uScalingFactor.x, 1.0 / uScalingFactor.y); - styleIndex = uint(floor(vStyleIndex + 0.5)); - gl_Position = uMVPMatrix * vec4(vPosition, 0.0, 1.0); + ) + (fadeInPattern ? OMMShaderCode( + // fadeInPattern + pixelPosition = vPosition.xy / vec2(uScreenPixelAsRealMeterFactor); + ) : OMMShaderCode( + // DefaultBehavior + pixelPosition = vPosition.xy / uScalingFactor; + )) + OMMShaderCode( + styleIndex = uint(floor(vStyleIndex + 0.5)); + gl_Position = uMVPMatrix * vec4(vPosition, 0.0, 1.0); } ); } @@ -65,6 +79,10 @@ std::string PolygonPatternGroup2dShaderOpenGl::getFragmentShader() { uniform vec2 uTextureFactor; uniform float textureCoordinates[5 * 16]; uniform float opacities[16]; + ) + (fadeInPattern ? OMMShaderCode( + uniform float uScreenPixelAsRealMeterFactor; + uniform vec2 uScalingFactor;) : "") + + OMMShaderCode( in vec2 pixelPosition; in flat uint styleIndex; @@ -78,21 +96,85 @@ std::string PolygonPatternGroup2dShaderOpenGl::getFragmentShader() { } int styleOffset = min(int(styleIndex) * 5, 16 * 5); - vec2 uvSize = vec2(textureCoordinates[styleOffset + 2], textureCoordinates[styleOffset + 3]) * uTextureFactor; + vec2 uvSize = + vec2(textureCoordinates[styleOffset + 2], textureCoordinates[styleOffset + 3]) * + uTextureFactor; if (uvSize.x == 0.0 && uvSize.y == 0.0) { discard; } - vec2 uvOrig = vec2(textureCoordinates[styleOffset], textureCoordinates[styleOffset + 1]) * uTextureFactor; + vec2 uvOrig = vec2(textureCoordinates[styleOffset], textureCoordinates[styleOffset + 1]) * + uTextureFactor; float combined = textureCoordinates[styleOffset + 4]; vec2 pixelSize = vec2(mod(combined, 65536.0), combined / 65536.0); + ) + (fadeInPattern ? OMMShaderCode( + // fadeInPattern + vec4 resultColor = vec4(0.0, 0.0, 0.0, 0.0); + float scalingFactorFactor = (uScalingFactor.x / uScreenPixelAsRealMeterFactor) - 1.0; + vec2 spacing = pixelSize * scalingFactorFactor; + vec2 totalSize = pixelSize + spacing; + vec2 adjustedPixelPosition = pixelPosition + pixelSize * 0.5; + vec2 uvTot = mod(adjustedPixelPosition, totalSize); + + int yIndex = int(mod(adjustedPixelPosition.y / totalSize.y, 2.0)); + + if (yIndex != 0 && uvTot.y <= pixelSize.y) { + uvTot.x = mod(adjustedPixelPosition.x + totalSize.x * 0.5, totalSize.x); + } - vec2 uv = mod(vec2(mod(pixelPosition.x, pixelSize.x), mod(pixelPosition.y, pixelSize.y)) / pixelSize + vec2(1.0, 1.0), vec2(1.0, 1.0)); - vec2 texUv = uvOrig + uvSize * uv; - vec4 color = texture(uTextureSampler, texUv); - - float a = color.a * opacity; - fragmentColor = vec4(color.rgb * a, a); + if (uvTot.x > pixelSize.x || uvTot.y > pixelSize.y) { + if (uvTot.x > pixelSize.x && uvTot.y < pixelSize.y) { + // top right + vec2 spacingTexSize = vec2(spacing.x, spacing.x); + float relative = uvTot.y - (pixelSize.y - spacing.x) / 2.0; + if (relative > 0.0 && relative < spacing.x) { + float xPos = uvTot.x - pixelSize.x; + vec2 uv = mod(vec2(xPos, relative) / spacingTexSize + vec2(1.0, 1.0), + vec2(1.0, 1.0)); + + vec2 texUv = uvOrig + uvSize * vec2(uv.x, uv.y); + vec4 texColor = texture(uTextureSampler, texUv); + resultColor = texColor; + } + } else { + uvTot.x = mod(adjustedPixelPosition.x + spacing.x * 0.5, totalSize.x); + if (uvTot.x > pixelSize.x && uvTot.y > pixelSize.y) { + // bottom right + vec2 uv = mod((uvTot - pixelSize) / spacing + vec2(1.0, 1.0), vec2(1.0, 1.0)); + + vec2 texUv = uvOrig + uvSize * vec2(uv.x, uv.y); + vec4 texColor = texture(uTextureSampler, texUv); + resultColor = texColor; + } else { + // bottom left + vec2 spacingTexSize = vec2(spacing.y, spacing.y); + float relativeX = uvTot.x - (pixelSize.x - spacing.x) / 2.0; + + if (relativeX > 0.0 && relativeX < spacing.y) { + vec2 uv = mod(vec2(relativeX, uvTot.y - pixelSize.y) / spacingTexSize + + vec2(1.0, 1.0), vec2(1.0, 1.0)); + vec2 texUv = uvOrig + uvSize * vec2(uv.x, uv.y); + vec4 texColor = texture(uTextureSampler, texUv); + resultColor = texColor; + } + } + } + } else { + vec2 uv = mod(uvTot / pixelSize + vec2(1.0, 1.0), vec2(1.0, 1.0)); + vec2 texUv = uvOrig + uvSize * vec2(uv.x, uv.y); + vec4 texColor = texture(uTextureSampler, texUv); + resultColor = texColor; + } + fragmentColor = resultColor; + } + ) : OMMShaderCode( + // Default pattern behavior + vec2 uv = mod(vec2(mod(pixelPosition.x, pixelSize.x), mod(pixelPosition.y, pixelSize.y)) / pixelSize + vec2(1.0, 1.0), vec2(1.0, 1.0)); + vec2 texUv = uvOrig + uvSize * uv; + vec4 color = texture(uTextureSampler, texUv); + + float a = color.a * opacity; + fragmentColor = vec4(color.rgb * a, a); } -); +)); } -std::shared_ptr PolygonPatternGroup2dShaderOpenGl::asShaderProgramInterface() { return shared_from_this(); } +std::shared_ptr PolygonPatternGroup2dShaderOpenGl::asShaderProgramInterface() { return shared_from_this(); } \ No newline at end of file diff --git a/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.h b/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.h index 1bbdad17f..5656422ed 100644 --- a/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.h +++ b/android/src/main/cpp/graphics/shader/PolygonPatternGroup2dShaderOpenGl.h @@ -21,6 +21,8 @@ class PolygonPatternGroup2dShaderOpenGl : public BaseShaderProgramOpenGl, public std::enable_shared_from_this { public: + PolygonPatternGroup2dShaderOpenGl(bool fadeInPattern); + virtual std::string getProgramName() override; virtual void setupProgram(const std::shared_ptr<::RenderingContextInterface> &context) override; @@ -30,7 +32,8 @@ class PolygonPatternGroup2dShaderOpenGl : public BaseShaderProgramOpenGl, virtual std::shared_ptr asShaderProgramInterface() override; protected: - const static std::string programName; + const bool fadeInPattern; + const std::string programName; virtual std::string getFragmentShader() override; diff --git a/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.cpp b/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.cpp index eee1c05ac..00b033220 100644 --- a/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.cpp +++ b/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.cpp @@ -50,8 +50,8 @@ std::shared_ptr ShaderFactoryOpenGl::createPolygonG return std::make_shared(); } -std::shared_ptr ShaderFactoryOpenGl::createPolygonPatternGroupShader() { - return std::make_shared(); +std::shared_ptr ShaderFactoryOpenGl::createPolygonPatternGroupShader(bool fadeInPattern) { + return std::make_shared(fadeInPattern); } std::shared_ptr ShaderFactoryOpenGl::createTextShader() { diff --git a/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.h b/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.h index 4387e4c1b..b18d7967a 100644 --- a/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.h +++ b/android/src/main/cpp/graphics/shader/ShaderFactoryOpenGl.h @@ -27,7 +27,7 @@ class ShaderFactoryOpenGl : public ShaderFactoryInterface { std::shared_ptr createPolygonGroupShader() override; - std::shared_ptr createPolygonPatternGroupShader() override; + std::shared_ptr createPolygonPatternGroupShader(bool fadeInPattern) override; std::shared_ptr createTextShader() override; diff --git a/android/src/main/java/io/openmobilemaps/mapscore/graphics/GLThread.kt b/android/src/main/java/io/openmobilemaps/mapscore/graphics/GLThread.kt index 9eba701dd..9ffe17bc4 100644 --- a/android/src/main/java/io/openmobilemaps/mapscore/graphics/GLThread.kt +++ b/android/src/main/java/io/openmobilemaps/mapscore/graphics/GLThread.kt @@ -390,6 +390,7 @@ class GLThread constructor( width = w height = h sizeChanged = true + requestRender() } } diff --git a/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/shader/ShaderFactoryInterface.kt b/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/shader/ShaderFactoryInterface.kt index 7eadb58a7..a37ab9a7a 100644 --- a/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/shader/ShaderFactoryInterface.kt +++ b/bridging/android/java/io/openmobilemaps/mapscore/shared/graphics/shader/ShaderFactoryInterface.kt @@ -20,7 +20,7 @@ abstract class ShaderFactoryInterface { abstract fun createPolygonGroupShader(): PolygonGroupShaderInterface - abstract fun createPolygonPatternGroupShader(): PolygonPatternGroupShaderInterface + abstract fun createPolygonPatternGroupShader(fadeInPattern: Boolean): PolygonPatternGroupShaderInterface abstract fun createTextShader(): TextShaderInterface @@ -83,11 +83,11 @@ abstract class ShaderFactoryInterface { } private external fun native_createPolygonGroupShader(_nativeRef: Long): PolygonGroupShaderInterface - override fun createPolygonPatternGroupShader(): PolygonPatternGroupShaderInterface { + override fun createPolygonPatternGroupShader(fadeInPattern: Boolean): PolygonPatternGroupShaderInterface { assert(!this.destroyed.get()) { error("trying to use a destroyed object") } - return native_createPolygonPatternGroupShader(this.nativeRef) + return native_createPolygonPatternGroupShader(this.nativeRef, fadeInPattern) } - private external fun native_createPolygonPatternGroupShader(_nativeRef: Long): PolygonPatternGroupShaderInterface + private external fun native_createPolygonPatternGroupShader(_nativeRef: Long, fadeInPattern: Boolean): PolygonPatternGroupShaderInterface override fun createTextShader(): TextShaderInterface { assert(!this.destroyed.get()) { error("trying to use a destroyed object") } diff --git a/bridging/android/java/io/openmobilemaps/mapscore/shared/map/MapCamera2dInterface.kt b/bridging/android/java/io/openmobilemaps/mapscore/shared/map/MapCamera2dInterface.kt index a740b9ea3..c029564ce 100644 --- a/bridging/android/java/io/openmobilemaps/mapscore/shared/map/MapCamera2dInterface.kt +++ b/bridging/android/java/io/openmobilemaps/mapscore/shared/map/MapCamera2dInterface.kt @@ -70,6 +70,8 @@ abstract class MapCamera2dInterface { abstract fun coordFromScreenPosition(posScreen: io.openmobilemaps.mapscore.shared.graphics.common.Vec2F): io.openmobilemaps.mapscore.shared.map.coordinates.Coord + abstract fun screenPosFromCoord(coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord): io.openmobilemaps.mapscore.shared.graphics.common.Vec2F + abstract fun mapUnitsFromPixels(distancePx: Double): Double abstract fun setRotationEnabled(enabled: Boolean) @@ -269,6 +271,12 @@ abstract class MapCamera2dInterface { } private external fun native_coordFromScreenPosition(_nativeRef: Long, posScreen: io.openmobilemaps.mapscore.shared.graphics.common.Vec2F): io.openmobilemaps.mapscore.shared.map.coordinates.Coord + override fun screenPosFromCoord(coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord): io.openmobilemaps.mapscore.shared.graphics.common.Vec2F { + assert(!this.destroyed.get()) { error("trying to use a destroyed object") } + return native_screenPosFromCoord(this.nativeRef, coord) + } + private external fun native_screenPosFromCoord(_nativeRef: Long, coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord): io.openmobilemaps.mapscore.shared.graphics.common.Vec2F + override fun mapUnitsFromPixels(distancePx: Double): Double { assert(!this.destroyed.get()) { error("trying to use a destroyed object") } return native_mapUnitsFromPixels(this.nativeRef, distancePx) diff --git a/bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/vector/Tiled2dMapVectorLayerInterface.kt b/bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/vector/Tiled2dMapVectorLayerInterface.kt index b142c008d..22f154fd1 100644 --- a/bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/vector/Tiled2dMapVectorLayerInterface.kt +++ b/bridging/android/java/io/openmobilemaps/mapscore/shared/map/layers/tiled/vector/Tiled2dMapVectorLayerInterface.kt @@ -40,6 +40,8 @@ abstract class Tiled2dMapVectorLayerInterface { abstract fun reloadLocalDataSource(sourceName: String, geoJson: String) + abstract fun performClick(coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord) + private class CppProxy : Tiled2dMapVectorLayerInterface { private val nativeRef: Long private val destroyed: AtomicBoolean = AtomicBoolean(false) @@ -126,5 +128,11 @@ abstract class Tiled2dMapVectorLayerInterface { native_reloadLocalDataSource(this.nativeRef, sourceName, geoJson) } private external fun native_reloadLocalDataSource(_nativeRef: Long, sourceName: String, geoJson: String) + + override fun performClick(coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord) { + assert(!this.destroyed.get()) { error("trying to use a destroyed object") } + native_performClick(this.nativeRef, coord) + } + private external fun native_performClick(_nativeRef: Long, coord: io.openmobilemaps.mapscore.shared.map.coordinates.Coord) } } diff --git a/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.cpp b/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.cpp index ff45d03b2..7c3ed424d 100644 --- a/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.cpp +++ b/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.cpp @@ -2,6 +2,7 @@ // This file was generated by Djinni from shader.djinni #include "NativeShaderFactoryInterface.h" // my header +#include "Marshal.hpp" #include "NativeAlphaInstancedShaderInterface.h" #include "NativeAlphaShaderInterface.h" #include "NativeColorCircleShaderInterface.h" @@ -73,11 +74,12 @@ NativeShaderFactoryInterface::JavaProxy::~JavaProxy() = default; ::djinni::jniExceptionCheck(jniEnv); return ::djinni_generated::NativePolygonGroupShaderInterface::toCpp(jniEnv, jret); } -/*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> NativeShaderFactoryInterface::JavaProxy::createPolygonPatternGroupShader() { +/*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> NativeShaderFactoryInterface::JavaProxy::createPolygonPatternGroupShader(bool c_fadeInPattern) { auto jniEnv = ::djinni::jniGetThreadEnv(); ::djinni::JniLocalScope jscope(jniEnv, 10); const auto& data = ::djinni::JniClass<::djinni_generated::NativeShaderFactoryInterface>::get(); - auto jret = jniEnv->CallObjectMethod(Handle::get().get(), data.method_createPolygonPatternGroupShader); + auto jret = jniEnv->CallObjectMethod(Handle::get().get(), data.method_createPolygonPatternGroupShader, + ::djinni::get(::djinni::Bool::fromCpp(jniEnv, c_fadeInPattern))); ::djinni::jniExceptionCheck(jniEnv); return ::djinni_generated::NativePolygonPatternGroupShaderInterface::toCpp(jniEnv, jret); } @@ -183,11 +185,11 @@ CJNIEXPORT jobject JNICALL Java_io_openmobilemaps_mapscore_shared_graphics_shade } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } -CJNIEXPORT jobject JNICALL Java_io_openmobilemaps_mapscore_shared_graphics_shader_ShaderFactoryInterface_00024CppProxy_native_1createPolygonPatternGroupShader(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef) +CJNIEXPORT jobject JNICALL Java_io_openmobilemaps_mapscore_shared_graphics_shader_ShaderFactoryInterface_00024CppProxy_native_1createPolygonPatternGroupShader(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, jboolean j_fadeInPattern) { try { const auto& ref = ::djinni::objectFromHandleAddress<::ShaderFactoryInterface>(nativeRef); - auto r = ref->createPolygonPatternGroupShader(); + auto r = ref->createPolygonPatternGroupShader(::djinni::Bool::toCpp(jniEnv, j_fadeInPattern)); return ::djinni::release(::djinni_generated::NativePolygonPatternGroupShaderInterface::fromCpp(jniEnv, r)); } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } diff --git a/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.h b/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.h index ce9f51ccd..1d96bdb50 100644 --- a/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.h +++ b/bridging/android/jni/graphics/shader/NativeShaderFactoryInterface.h @@ -39,7 +39,7 @@ class NativeShaderFactoryInterface final : ::djinni::JniInterface<::ShaderFactor /*not-null*/ std::shared_ptr<::ColorShaderInterface> createColorShader() override; /*not-null*/ std::shared_ptr<::ColorCircleShaderInterface> createColorCircleShader() override; /*not-null*/ std::shared_ptr<::PolygonGroupShaderInterface> createPolygonGroupShader() override; - /*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> createPolygonPatternGroupShader() override; + /*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> createPolygonPatternGroupShader(bool fadeInPattern) override; /*not-null*/ std::shared_ptr<::TextShaderInterface> createTextShader() override; /*not-null*/ std::shared_ptr<::TextInstancedShaderInterface> createTextInstancedShader() override; /*not-null*/ std::shared_ptr<::RasterShaderInterface> createRasterShader() override; @@ -57,7 +57,7 @@ class NativeShaderFactoryInterface final : ::djinni::JniInterface<::ShaderFactor const jmethodID method_createColorShader { ::djinni::jniGetMethodID(clazz.get(), "createColorShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/ColorShaderInterface;") }; const jmethodID method_createColorCircleShader { ::djinni::jniGetMethodID(clazz.get(), "createColorCircleShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/ColorCircleShaderInterface;") }; const jmethodID method_createPolygonGroupShader { ::djinni::jniGetMethodID(clazz.get(), "createPolygonGroupShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/PolygonGroupShaderInterface;") }; - const jmethodID method_createPolygonPatternGroupShader { ::djinni::jniGetMethodID(clazz.get(), "createPolygonPatternGroupShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/PolygonPatternGroupShaderInterface;") }; + const jmethodID method_createPolygonPatternGroupShader { ::djinni::jniGetMethodID(clazz.get(), "createPolygonPatternGroupShader", "(Z)Lio/openmobilemaps/mapscore/shared/graphics/shader/PolygonPatternGroupShaderInterface;") }; const jmethodID method_createTextShader { ::djinni::jniGetMethodID(clazz.get(), "createTextShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/TextShaderInterface;") }; const jmethodID method_createTextInstancedShader { ::djinni::jniGetMethodID(clazz.get(), "createTextInstancedShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/TextInstancedShaderInterface;") }; const jmethodID method_createRasterShader { ::djinni::jniGetMethodID(clazz.get(), "createRasterShader", "()Lio/openmobilemaps/mapscore/shared/graphics/shader/RasterShaderInterface;") }; diff --git a/bridging/android/jni/map/NativeMapCamera2dInterface.cpp b/bridging/android/jni/map/NativeMapCamera2dInterface.cpp index 015b91b3e..4cb87f049 100644 --- a/bridging/android/jni/map/NativeMapCamera2dInterface.cpp +++ b/bridging/android/jni/map/NativeMapCamera2dInterface.cpp @@ -280,6 +280,15 @@ CJNIEXPORT ::djinni_generated::NativeCoord::JniType JNICALL Java_io_openmobilema } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) } +CJNIEXPORT ::djinni_generated::NativeVec2F::JniType JNICALL Java_io_openmobilemaps_mapscore_shared_map_MapCamera2dInterface_00024CppProxy_native_1screenPosFromCoord(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, ::djinni_generated::NativeCoord::JniType j_coord) +{ + try { + const auto& ref = ::djinni::objectFromHandleAddress<::MapCamera2dInterface>(nativeRef); + auto r = ref->screenPosFromCoord(::djinni_generated::NativeCoord::toCpp(jniEnv, j_coord)); + return ::djinni::release(::djinni_generated::NativeVec2F::fromCpp(jniEnv, r)); + } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, 0 /* value doesn't matter */) +} + CJNIEXPORT jdouble JNICALL Java_io_openmobilemaps_mapscore_shared_map_MapCamera2dInterface_00024CppProxy_native_1mapUnitsFromPixels(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, jdouble j_distancePx) { try { diff --git a/bridging/android/jni/map/layers/tiled/vector/NativeTiled2dMapVectorLayerInterface.cpp b/bridging/android/jni/map/layers/tiled/vector/NativeTiled2dMapVectorLayerInterface.cpp index c8a416b53..a09958efd 100644 --- a/bridging/android/jni/map/layers/tiled/vector/NativeTiled2dMapVectorLayerInterface.cpp +++ b/bridging/android/jni/map/layers/tiled/vector/NativeTiled2dMapVectorLayerInterface.cpp @@ -3,6 +3,7 @@ #include "NativeTiled2dMapVectorLayerInterface.h" // my header #include "Marshal.hpp" +#include "NativeCoord.h" #include "NativeFontLoaderInterface.h" #include "NativeLayerInterface.h" #include "NativeLoaderInterface.h" @@ -156,4 +157,12 @@ CJNIEXPORT void JNICALL Java_io_openmobilemaps_mapscore_shared_map_layers_tiled_ } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) } +CJNIEXPORT void JNICALL Java_io_openmobilemaps_mapscore_shared_map_layers_tiled_vector_Tiled2dMapVectorLayerInterface_00024CppProxy_native_1performClick(JNIEnv* jniEnv, jobject /*this*/, jlong nativeRef, ::djinni_generated::NativeCoord::JniType j_coord) +{ + try { + const auto& ref = ::djinni::objectFromHandleAddress<::Tiled2dMapVectorLayerInterface>(nativeRef); + ref->performClick(::djinni_generated::NativeCoord::toCpp(jniEnv, j_coord)); + } JNI_TRANSLATE_EXCEPTIONS_RETURN(jniEnv, ) +} + } // namespace djinni_generated diff --git a/bridging/ios/MCMapCamera2dInterface+Private.mm b/bridging/ios/MCMapCamera2dInterface+Private.mm index 3cfbb9b66..31dffde6d 100644 --- a/bridging/ios/MCMapCamera2dInterface+Private.mm +++ b/bridging/ios/MCMapCamera2dInterface+Private.mm @@ -247,6 +247,13 @@ - (nonnull MCCoord *)coordFromScreenPosition:(nonnull MCVec2F *)posScreen { } DJINNI_TRANSLATE_EXCEPTIONS() } +- (nonnull MCVec2F *)screenPosFromCoord:(nonnull MCCoord *)coord { + try { + auto objcpp_result_ = _cppRefHandle.get()->screenPosFromCoord(::djinni_generated::Coord::toCpp(coord)); + return ::djinni_generated::Vec2F::fromCpp(objcpp_result_); + } DJINNI_TRANSLATE_EXCEPTIONS() +} + - (double)mapUnitsFromPixels:(double)distancePx { try { auto objcpp_result_ = _cppRefHandle.get()->mapUnitsFromPixels(::djinni::F64::toCpp(distancePx)); diff --git a/bridging/ios/MCMapCamera2dInterface.h b/bridging/ios/MCMapCamera2dInterface.h index 9377108a8..8be1bd2f7 100644 --- a/bridging/ios/MCMapCamera2dInterface.h +++ b/bridging/ios/MCMapCamera2dInterface.h @@ -84,6 +84,8 @@ - (nonnull MCCoord *)coordFromScreenPosition:(nonnull MCVec2F *)posScreen; +- (nonnull MCVec2F *)screenPosFromCoord:(nonnull MCCoord *)coord; + - (double)mapUnitsFromPixels:(double)distancePx; - (void)setRotationEnabled:(BOOL)enabled; diff --git a/bridging/ios/MCShaderFactoryInterface+Private.mm b/bridging/ios/MCShaderFactoryInterface+Private.mm index 71bd80e4e..dcd7124e5 100644 --- a/bridging/ios/MCShaderFactoryInterface+Private.mm +++ b/bridging/ios/MCShaderFactoryInterface+Private.mm @@ -85,9 +85,9 @@ - (id)initWithCpp:(const std::shared_ptr<::ShaderFactoryInterface>&)cppRef } DJINNI_TRANSLATE_EXCEPTIONS() } -- (nullable id)createPolygonPatternGroupShader { +- (nullable id)createPolygonPatternGroupShader:(BOOL)fadeInPattern { try { - auto objcpp_result_ = _cppRefHandle.get()->createPolygonPatternGroupShader(); + auto objcpp_result_ = _cppRefHandle.get()->createPolygonPatternGroupShader(::djinni::Bool::toCpp(fadeInPattern)); return ::djinni_generated::PolygonPatternGroupShaderInterface::fromCpp(objcpp_result_); } DJINNI_TRANSLATE_EXCEPTIONS() } @@ -178,10 +178,10 @@ - (id)initWithCpp:(const std::shared_ptr<::ShaderFactoryInterface>&)cppRef return ::djinni_generated::PolygonGroupShaderInterface::toCpp(objcpp_result_); } } - /*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> createPolygonPatternGroupShader() override + /*not-null*/ std::shared_ptr<::PolygonPatternGroupShaderInterface> createPolygonPatternGroupShader(bool c_fadeInPattern) override { @autoreleasepool { - auto objcpp_result_ = [djinni_private_get_proxied_objc_object() createPolygonPatternGroupShader]; + auto objcpp_result_ = [djinni_private_get_proxied_objc_object() createPolygonPatternGroupShader:(::djinni::Bool::fromCpp(c_fadeInPattern))]; return ::djinni_generated::PolygonPatternGroupShaderInterface::toCpp(objcpp_result_); } } diff --git a/bridging/ios/MCShaderFactoryInterface.h b/bridging/ios/MCShaderFactoryInterface.h index df9555bb2..f8eeb05f6 100644 --- a/bridging/ios/MCShaderFactoryInterface.h +++ b/bridging/ios/MCShaderFactoryInterface.h @@ -30,7 +30,7 @@ - (nullable id)createPolygonGroupShader; -- (nullable id)createPolygonPatternGroupShader; +- (nullable id)createPolygonPatternGroupShader:(BOOL)fadeInPattern; - (nullable id)createTextShader; diff --git a/bridging/ios/MCTiled2dMapVectorLayerInterface+Private.mm b/bridging/ios/MCTiled2dMapVectorLayerInterface+Private.mm index 8b707940e..def117e06 100644 --- a/bridging/ios/MCTiled2dMapVectorLayerInterface+Private.mm +++ b/bridging/ios/MCTiled2dMapVectorLayerInterface+Private.mm @@ -6,6 +6,7 @@ #import "DJICppWrapperCache+Private.h" #import "DJIError.h" #import "DJIMarshal+Private.h" +#import "MCCoord+Private.h" #import "MCFontLoaderInterface+Private.h" #import "MCLayerInterface+Private.h" #import "MCLoaderInterface+Private.h" @@ -155,6 +156,12 @@ - (void)reloadLocalDataSource:(nonnull NSString *)sourceName } DJINNI_TRANSLATE_EXCEPTIONS() } +- (void)performClick:(nonnull MCCoord *)coord { + try { + _cppRefHandle.get()->performClick(::djinni_generated::Coord::toCpp(coord)); + } DJINNI_TRANSLATE_EXCEPTIONS() +} + namespace djinni_generated { auto Tiled2dMapVectorLayerInterface::toCpp(ObjcType objc) -> CppType diff --git a/bridging/ios/MCTiled2dMapVectorLayerInterface.h b/bridging/ios/MCTiled2dMapVectorLayerInterface.h index 1daa2c756..08cf479af 100644 --- a/bridging/ios/MCTiled2dMapVectorLayerInterface.h +++ b/bridging/ios/MCTiled2dMapVectorLayerInterface.h @@ -1,6 +1,7 @@ // AUTOGENERATED FILE - DO NOT MODIFY! // This file was generated by Djinni from tiled_vector_layer.djinni +#import "MCCoord.h" #import "MCFontLoaderInterface.h" #import "MCLayerInterface.h" #import "MCLoaderInterface.h" @@ -71,4 +72,6 @@ - (void)reloadLocalDataSource:(nonnull NSString *)sourceName geoJson:(nonnull NSString *)geoJson; +- (void)performClick:(nonnull MCCoord *)coord; + @end diff --git a/djinni/graphics/shader/shader.djinni b/djinni/graphics/shader/shader.djinni index 3a4229482..c7c74dc49 100644 --- a/djinni/graphics/shader/shader.djinni +++ b/djinni/graphics/shader/shader.djinni @@ -25,7 +25,7 @@ shader_factory_interface = interface +c +j +o { create_color_shader() : color_shader_interface; create_color_circle_shader() : color_circle_shader_interface; create_polygon_group_shader(): polygon_group_shader_interface; - create_polygon_pattern_group_shader(): polygon_pattern_group_shader_interface; + create_polygon_pattern_group_shader(fade_in_pattern: bool): polygon_pattern_group_shader_interface; create_text_shader() : text_shader_interface; create_text_instanced_shader(): text_instanced_shader_interface; diff --git a/djinni/map/core.djinni b/djinni/map/core.djinni index f735e76b3..64fa3601d 100644 --- a/djinni/map/core.djinni +++ b/djinni/map/core.djinni @@ -156,6 +156,7 @@ map_camera_2d_interface = interface +c { remove_listener(listener: map_camera_2d_listener_interface); coord_from_screen_position(pos_screen: vec_2_f): coord; + screen_pos_from_coord(coord: coord): vec_2_f; map_units_from_pixels(distancePx: f64): f64; set_rotation_enabled(enabled: bool); diff --git a/djinni/map/layers/tiled/vector/tiled_vector_layer.djinni b/djinni/map/layers/tiled/vector/tiled_vector_layer.djinni index 699db07d6..8597287b6 100644 --- a/djinni/map/layers/tiled/vector/tiled_vector_layer.djinni +++ b/djinni/map/layers/tiled/vector/tiled_vector_layer.djinni @@ -63,6 +63,8 @@ sourceUrlParams: optional> reload_data_source(source_name: string); reload_local_data_source(source_name: string, geo_json: string); + + perform_click(coord: coord); } vector_layer_feature_info_value = record { diff --git a/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift b/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift index 58eb84dc0..9dc7b5a64 100644 --- a/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift +++ b/ios/graphics/Model/Polygon/PolygonPatternGroup2d.swift @@ -23,11 +23,15 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { private var textureCoordinatesBuffer: MTLBuffer? private var stencilState: MTLDepthStencilState? + private var renderPassStencilState: MTLDepthStencilState? private var texture: MTLTexture? private var screenPixelFactor: Float = 0 var customScreenPixelFactor = SIMD2([0.0, 0.0]) + + var posOffset = SIMD2([0.0, 0.0]) + init(shader: MCShaderProgramInterface, metalContext: MetalContext) { guard let shader = shader as? PolygonPatternGroupShader else { @@ -39,25 +43,9 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { label: "PolygonPatternGroup2d") } - private func setupStencilStates() { - let ss2 = MTLStencilDescriptor() - ss2.stencilCompareFunction = .equal - ss2.stencilFailureOperation = .zero - ss2.depthFailureOperation = .keep - ss2.depthStencilPassOperation = .keep - ss2.readMask = 0b1111_1111 - ss2.writeMask = 0b0000_0000 - - let s2 = MTLDepthStencilDescriptor() - s2.frontFaceStencil = ss2 - s2.backFaceStencil = ss2 - - stencilState = device.makeDepthStencilState(descriptor: s2) - } - override func render(encoder: MTLRenderCommandEncoder, context: RenderingContext, - renderPass _: MCRenderPassConfig, + renderPass pass: MCRenderPassConfig, mvpMatrix: Int64, isMasked: Bool, screenPixelAsRealMeterFactor: Double) { @@ -70,7 +58,9 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { let indicesBuffer, let opacitiesBuffer, let textureCoordinatesBuffer, - let texture else { return } + let texture else { + return + } #if DEBUG encoder.pushDebugGroup(label) @@ -81,12 +71,22 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { if isMasked { if stencilState == nil { - setupStencilStates() + self.stencilState = self.maskStencilState() } + encoder.setDepthStencilState(stencilState) encoder.setStencilReferenceValue(0b1100_0000) } + if pass.isPassMasked { + if renderPassStencilState == nil { + renderPassStencilState = self.renderPassMaskStencilState() + } + + encoder.setDepthStencilState(renderPassStencilState) + encoder.setStencilReferenceValue(0b1100_0000) + } + shader.setupProgram(context) shader.preRender(context) @@ -94,13 +94,24 @@ final class PolygonPatternGroup2d: BaseGraphicsObject { if let matrixPointer = UnsafeRawPointer(bitPattern: Int(mvpMatrix)) { encoder.setVertexBytes(matrixPointer, length: 64, index: 1) } - if customScreenPixelFactor.x != 0 { - encoder.setVertexBytes(&customScreenPixelFactor, length: MemoryLayout>.stride, index: 2) + + // scale factors for shaders + var pixelFactor : Float = Float(screenPixelAsRealMeterFactor) + + if self.shader.fadeInPattern { + var scaleFactors = SIMD2([pixelFactor, pixelFactor]) + encoder.setVertexBytes(&scaleFactors, length: MemoryLayout>.stride, index: 2) + encoder.setVertexBytes(&posOffset, length: MemoryLayout>.stride, index: 3) + + scaleFactors = customScreenPixelFactor.x != 0 ? customScreenPixelFactor : SIMD2([pixelFactor, pixelFactor]) + encoder.setFragmentBytes(&pixelFactor, length: MemoryLayout.stride, index: 2) + encoder.setFragmentBytes(&scaleFactors, length: MemoryLayout>.stride, index: 3) } else { - var factors = SIMD2([screenPixelAsRealMeterFactor, screenPixelAsRealMeterFactor]) - encoder.setVertexBytes(&factors, length: MemoryLayout>.stride, index: 2) + var scaleFactors = customScreenPixelFactor.x != 0 ? customScreenPixelFactor : SIMD2([pixelFactor, pixelFactor]) + encoder.setVertexBytes(&scaleFactors, length: MemoryLayout>.stride, index: 2) } + // texture encoder.setFragmentTexture(texture, index: 0) encoder.setFragmentSamplerState(sampler, index: 0) @@ -135,6 +146,23 @@ extension PolygonPatternGroup2d: MCPolygonPatternGroup2dInterface { self.indicesCount = Int(indices.elementCount) self.verticesBuffer = verticesBuffer self.indicesBuffer = indicesBuffer + + if let p = UnsafeRawPointer(bitPattern: Int(vertices.address)) { + var minX = Float.greatestFiniteMagnitude + var minY = Float.greatestFiniteMagnitude + + for i in 0.. texture0 [[ texture(0)]], + sampler textureSampler [[sampler(0)]], + constant float *opacity [[buffer(0)]], + constant float *texureCoordinates [[buffer(1)]], + constant float &screenPixelAsRealMeterFactor [[buffer(2)]], + constant float2 &scalingFactor [[buffer(3)]]) +{ + + int offset = int(in.stylingIndex * 5); + const float2 uvOrig = float2(texureCoordinates[offset], texureCoordinates[offset + 1]); + const float2 uvSize = float2(texureCoordinates[offset + 2], texureCoordinates[offset + 3]); + const int combined = int(texureCoordinates[offset + 4]); + const float2 pixelSize = float2(combined & 0xFF, combined >> 16); + + const float scalingFactorFactor = (scalingFactor.x / screenPixelAsRealMeterFactor) - 1.0; + const float2 spacing = pixelSize * scalingFactorFactor; + const float2 totalSize = pixelSize + spacing; + const float2 adjustedPixelPosition = in.pixelPosition + totalSize * 0.5; // in other project pixelSize + float2 uvTot = fmod(adjustedPixelPosition, totalSize); + + const int yIndex = int(adjustedPixelPosition.y / totalSize.y) % 2; + + if(yIndex != 0 && uvTot.y <= pixelSize.y) { + uvTot.x = fmod(adjustedPixelPosition.x + totalSize.x * 0.5, totalSize.x); + } + + float4 resultColor = float4(0.0,0.0,0.0,0.0); + + if(uvTot.x > pixelSize.x || uvTot.y > pixelSize.y) { + if(uvTot.x > pixelSize.x && uvTot.y < pixelSize.y) { + // topRight + const float2 spacingTexSize = float2(spacing.x, spacing.x); + float relative = uvTot.y - (pixelSize.y - spacing.x) / 2; + if(relative > 0.0 && relative < spacing.x) { + float xPos = uvTot.x - pixelSize.x; + float2 uv = fmod(float2(xPos, relative) / spacingTexSize + float2(1.0,1.0), float2(1.0,1.0)); + + const float2 texUv = uvOrig + uvSize * uv; + resultColor = texture0.sample(textureSampler, texUv); + } + } else { + uvTot.x = fmod(adjustedPixelPosition.x + spacing.x * 0.5, totalSize.x); + if(uvTot.x > pixelSize.x && uvTot.y > pixelSize.y) { + // bottom right + const float2 uv = fmod((uvTot - pixelSize) / spacing + float2(1.0, 1.0), float2(1.0,1.0)); + const float2 texUv = uvOrig + uvSize * uv; + resultColor = texture0.sample(textureSampler, texUv); + } else { + // bottom left + const float2 spacingTexSize = float2(spacing.y, spacing.y); + const float relativeX = uvTot.x - (pixelSize.x - spacing.x) / 2.0; + + if(relativeX > 0.0 && relativeX < spacing.y) { + const float2 uv = fmod(float2(relativeX, uvTot.y - pixelSize.y) / spacingTexSize + float2(1.0, 1.0), float2(1.0,1.0)); + const float2 texUv = uvOrig + uvSize * uv; + resultColor = texture0.sample(textureSampler, texUv); + } + } + } + } else { + const float2 uv = fmod(uvTot / pixelSize + float2(1.0,1.0), float2(1.0,1.0)); + const float2 texUv = uvOrig + uvSize * uv; + resultColor = texture0.sample(textureSampler, texUv); + } + + return resultColor; +} diff --git a/ios/graphics/Shader/PolygonPatternGroupShader.swift b/ios/graphics/Shader/PolygonPatternGroupShader.swift index c737469d7..833a06557 100644 --- a/ios/graphics/Shader/PolygonPatternGroupShader.swift +++ b/ios/graphics/Shader/PolygonPatternGroupShader.swift @@ -14,13 +14,25 @@ import Metal import UIKit class PolygonPatternGroupShader: BaseShader { - override init() { + // MARK: - Variables + + let fadeInPattern : Bool + + // MARK: - Init + + init(fadeInPattern: Bool) { + self.fadeInPattern = fadeInPattern + super.init() } + // MARK: - Setup + override func setupProgram(_: MCRenderingContextInterface?) { - if pipeline == nil { - pipeline = MetalContext.current.pipelineLibrary.value(Pipeline(type: .polygonPatternGroupShader, blendMode: blendMode).json) - } + guard pipeline == nil else { return } + + let t : PipelineType = fadeInPattern ? .polygonPatternFadeInGroupShader : .polygonPatternGroupShader + let pl = Pipeline(type: t, blendMode: blendMode) + pipeline = MetalContext.current.pipelineLibrary.value(pl.json) } override func preRender(encoder: MTLRenderCommandEncoder, context: RenderingContext) { diff --git a/ios/graphics/Shader/ShaderFactory.swift b/ios/graphics/Shader/ShaderFactory.swift index 94b60751d..f957b2043 100644 --- a/ios/graphics/Shader/ShaderFactory.swift +++ b/ios/graphics/Shader/ShaderFactory.swift @@ -20,8 +20,8 @@ class ShaderFactory: MCShaderFactoryInterface { PolygonGroupShader() } - func createPolygonPatternGroupShader() -> MCPolygonPatternGroupShaderInterface? { - PolygonPatternGroupShader() + func createPolygonPatternGroupShader(_ fadeInPattern: Bool) -> MCPolygonPatternGroupShaderInterface? { + PolygonPatternGroupShader(fadeInPattern: fadeInPattern) } func createColorCircleShader() -> MCColorCircleShaderInterface? { diff --git a/shared/public/MapCamera2dInterface.h b/shared/public/MapCamera2dInterface.h index 5389fa030..4ddbef645 100644 --- a/shared/public/MapCamera2dInterface.h +++ b/shared/public/MapCamera2dInterface.h @@ -77,6 +77,8 @@ class MapCamera2dInterface { virtual ::Coord coordFromScreenPosition(const ::Vec2F & posScreen) = 0; + virtual ::Vec2F screenPosFromCoord(const ::Coord & coord) = 0; + virtual double mapUnitsFromPixels(double distancePx) = 0; virtual void setRotationEnabled(bool enabled) = 0; diff --git a/shared/public/PolygonVectorLayerDescription.h b/shared/public/PolygonVectorLayerDescription.h index 84cc869ca..faf27c70b 100644 --- a/shared/public/PolygonVectorLayerDescription.h +++ b/shared/public/PolygonVectorLayerDescription.h @@ -20,17 +20,20 @@ class PolygonVectorStyle { PolygonVectorStyle(std::shared_ptr fillColor, std::shared_ptr fillOpacity, std::shared_ptr fillPattern, - std::shared_ptr blendMode): + std::shared_ptr blendMode, + bool fadeInPattern): fillColor(fillColor), fillOpacity(fillOpacity), fillPattern(fillPattern), - blendMode(blendMode) {} + blendMode(blendMode), + fadeInPattern(fadeInPattern) {} PolygonVectorStyle(PolygonVectorStyle &style) : fillColor(style.fillColor), fillOpacity(style.fillOpacity), fillPattern(style.fillPattern), - blendMode(style.blendMode) {} + blendMode(style.blendMode), + fadeInPattern(style.fadeInPattern) {} UsedKeysCollection getUsedKeys() const { @@ -77,7 +80,8 @@ class PolygonVectorStyle { std::shared_ptr fillOpacity; std::shared_ptr fillPattern; std::shared_ptr blendMode; - + bool fadeInPattern; + private: ValueEvaluator fillColorEvaluator; ValueEvaluator fillOpacityEvaluator; diff --git a/shared/public/ShaderFactoryInterface.h b/shared/public/ShaderFactoryInterface.h index a0d56fdf0..81b90daee 100644 --- a/shared/public/ShaderFactoryInterface.h +++ b/shared/public/ShaderFactoryInterface.h @@ -34,7 +34,7 @@ class ShaderFactoryInterface { virtual /*not-null*/ std::shared_ptr createPolygonGroupShader() = 0; - virtual /*not-null*/ std::shared_ptr createPolygonPatternGroupShader() = 0; + virtual /*not-null*/ std::shared_ptr createPolygonPatternGroupShader(bool fadeInPattern) = 0; virtual /*not-null*/ std::shared_ptr createTextShader() = 0; diff --git a/shared/public/Tiled2dMapVectorLayer.h b/shared/public/Tiled2dMapVectorLayer.h index aa2c714ed..767f6f776 100644 --- a/shared/public/Tiled2dMapVectorLayer.h +++ b/shared/public/Tiled2dMapVectorLayer.h @@ -155,6 +155,8 @@ class Tiled2dMapVectorLayer std::optional getMaxZoomLevelIdentifier() override; + void performClick(const Coord &coord) override; + // Touch Interface bool onTouchDown(const Vec2F &posScreen) override; diff --git a/shared/public/Tiled2dMapVectorLayerInterface.h b/shared/public/Tiled2dMapVectorLayerInterface.h index e9d5432f1..8ab0f5f48 100644 --- a/shared/public/Tiled2dMapVectorLayerInterface.h +++ b/shared/public/Tiled2dMapVectorLayerInterface.h @@ -3,6 +3,7 @@ #pragma once +#include "Coord.h" #include "FontLoaderInterface.h" #include "LayerInterface.h" #include "LoaderInterface.h" @@ -65,4 +66,6 @@ class Tiled2dMapVectorLayerInterface { virtual void reloadDataSource(const std::string & sourceName) = 0; virtual void reloadLocalDataSource(const std::string & sourceName, const std::string & geoJson) = 0; + + virtual void performClick(const ::Coord & coord) = 0; }; diff --git a/shared/public/Tiled2dMapVectorTile.h b/shared/public/Tiled2dMapVectorTile.h index ce12ec9b0..33c780365 100644 --- a/shared/public/Tiled2dMapVectorTile.h +++ b/shared/public/Tiled2dMapVectorTile.h @@ -65,6 +65,8 @@ class Tiled2dMapVectorTile : public ActorObject, void setSelectionDelegate(const std::weak_ptr &selectionDelegate); + virtual bool performClick(const Coord &coord) = 0; + protected: const std::weak_ptr mapInterface; const Tiled2dMapVersionedTileInfo tileInfo; diff --git a/shared/src/map/camera/MapCamera2d.cpp b/shared/src/map/camera/MapCamera2d.cpp index ffb4bdcc7..c24000485 100644 --- a/shared/src/map/camera/MapCamera2d.cpp +++ b/shared/src/map/camera/MapCamera2d.cpp @@ -19,6 +19,7 @@ #include "Vec2D.h" #include "Vec2DHelper.h" #include "Vec2FHelper.h" +#include "Logger.h" #define DEFAULT_ANIM_LENGTH 300 #define ROTATION_THRESHOLD 20 @@ -733,6 +734,35 @@ Coord MapCamera2d::coordFromScreenPosition(const ::Vec2F &posScreen) { return Coord(centerPosition.systemIdentifier, centerPosition.x + adjXDiff, centerPosition.y - adjYDiff, centerPosition.z); } +::Vec2F MapCamera2d::screenPosFromCoord(const Coord &coord) { + const auto mapInterface = this->mapInterface; + const auto conversionHelper = mapInterface ? mapInterface->getCoordinateConverterHelper() : nullptr; + const auto renderingContext = mapInterface ? mapInterface->getRenderingContext() : nullptr; + if (!conversionHelper || !renderingContext) { + return Vec2F(0.0, 0.0); + } + + const auto mapCoord = conversionHelper->convert(mapCoordinateSystem.identifier, coord); + + double angRad = -angle * M_PI / 180.0; + double sinAng = std::sin(angRad); + double cosAng = std::cos(angRad); + + double coordXDiffToCenter = mapCoord.x - centerPosition.x; + double coordYDiffToCenter = mapCoord.y - centerPosition.y; + + double screenXDiffToCenter = coordXDiffToCenter * cosAng - coordYDiffToCenter * sinAng; + double screenYDiffToCenter = coordXDiffToCenter * sinAng + coordYDiffToCenter * cosAng; + + const Vec2I sizeViewport = renderingContext->getViewportSize(); + + double zoomFactor = screenPixelAsRealMeterFactor * zoom; + double posScreenX = (screenXDiffToCenter / zoomFactor) + ((double)sizeViewport.x / 2.0); + double posScreenY = ((double)sizeViewport.y / 2.0) - (screenYDiffToCenter / zoomFactor); + + return Vec2F(posScreenX, posScreenY); +} + double MapCamera2d::mapUnitsFromPixels(double distancePx) { return distancePx * screenPixelAsRealMeterFactor * zoom; } double MapCamera2d::getScalingFactor() { return mapUnitsFromPixels(1.0); } diff --git a/shared/src/map/camera/MapCamera2d.h b/shared/src/map/camera/MapCamera2d.h index 814d9bfe5..8453690cf 100644 --- a/shared/src/map/camera/MapCamera2d.h +++ b/shared/src/map/camera/MapCamera2d.h @@ -20,6 +20,7 @@ #include "MapCoordinateSystem.h" #include "SimpleTouchInterface.h" #include "Vec2I.h" +#include "Vec2F.h" #include #include #include @@ -120,6 +121,8 @@ class MapCamera2d : public MapCamera2dInterface, virtual ::Coord coordFromScreenPosition(const ::Vec2F &posScreen) override; + Vec2F screenPosFromCoord(const Coord &coord) override; + virtual double mapUnitsFromPixels(double distancePx) override; virtual double getScalingFactor() override; diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp index 39bc0d033..068e3b6f9 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayer.cpp @@ -1143,6 +1143,18 @@ bool Tiled2dMapVectorLayer::onClickConfirmed(const Vec2F &posScreen) { return false; } +void Tiled2dMapVectorLayer::performClick(const Coord &coord) { + const auto mapInterface = this->mapInterface; + const auto camera = mapInterface ? mapInterface->getCamera() : nullptr; + + if (!camera) { + return; + } + + const auto screenPos = camera->screenPosFromCoord(coord); + onClickConfirmed(screenPos); +} + bool Tiled2dMapVectorLayer::onDoubleClick(const Vec2F &posScreen) { return interactionManager->onDoubleClick(posScreen); } diff --git a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp index 18b412e5c..f688f4e70 100644 --- a/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp +++ b/shared/src/map/layers/tiled/vector/Tiled2dMapVectorLayerParserHelper.cpp @@ -380,7 +380,8 @@ Tiled2dMapVectorLayerParserResult Tiled2dMapVectorLayerParserHelper::parseStyleJ PolygonVectorStyle style(parser.parseValue(val["paint"]["fill-color"]), parser.parseValue(val["paint"]["fill-opacity"]), parser.parseValue(val["paint"]["fill-pattern"]), - blendMode); + blendMode, + (!val["layout"]["fadeInPattern"].is_null()) && val["layout"].value("fadeInPattern", false)); auto layerDesc = std::make_shared(val["id"], val["source"], diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h index b7a064bc0..f327579ea 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceDataManager.h @@ -72,6 +72,8 @@ class Tiled2dMapVectorSourceDataManager : public ActorObject { virtual void clearTouch() = 0; + virtual bool performClick(const std::unordered_set &layers, const Coord &coord) = 0; + virtual void setSprites(std::shared_ptr spriteData, std::shared_ptr spriteTexture) {} protected: diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp index 26c37e7f8..5838fd39a 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.cpp @@ -417,6 +417,31 @@ Tiled2dMapVectorSourceTileDataManager::onClickConfirmed(const std::unordered_set return false; } +bool Tiled2dMapVectorSourceTileDataManager::performClick(const std::unordered_set &layers, const Coord &coord) { + if (interactableLayers.empty()) { + return false; + } + for (const auto &[tileInfo, subTiles]: tiles) { + const auto tileState = tileStateMap.find(tileInfo); + if (tileState == tileStateMap.end() || tileState->second != TileState::VISIBLE) { + continue; + } + for (auto rIter = subTiles.rbegin(); rIter != subTiles.rend(); rIter++) { + if (interactableLayers.count(std::get<1>(*rIter)) == 0 || layers.count(std::get<1>(*rIter)) == 0) { + continue; + } + bool hit = std::get<2>(*rIter).syncAccess([coord](auto tile) { + return tile->performClick(coord); + }); + if (hit) { + return true; + } + } + } + return false; +} + + bool Tiled2dMapVectorSourceTileDataManager::onDoubleClick(const std::unordered_set &layers, const Vec2F &posScreen) { if (interactableLayers.empty()) { return false; diff --git a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.h b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.h index 81b884009..492c26ba2 100644 --- a/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.h +++ b/shared/src/map/layers/tiled/vector/sourcemanagers/Tiled2dMapVectorSourceTileDataManager.h @@ -14,10 +14,11 @@ #include "SpriteData.h" class Tiled2dMapVectorLayer; + class Tiled2dMapVectorTile; class Tiled2dMapVectorSourceTileDataManager : public Tiled2dMapVectorLayerTileCallbackInterface, - public Tiled2dMapVectorSourceDataManager, + public Tiled2dMapVectorSourceDataManager, public std::enable_shared_from_this { public: using Tiled2dMapVectorSourceDataManager::Tiled2dMapVectorSourceDataManager; @@ -52,6 +53,8 @@ class Tiled2dMapVectorSourceTileDataManager : public Tiled2dMapVectorLayerTileCa void clearTouch() override; + bool performClick(const std::unordered_set &layers, const Coord &coord) override; + void setSprites(std::shared_ptr spriteData, std::shared_ptr spriteTexture) override; virtual void reloadLayerContent(const std::vector, int32_t>> &descriptionLayerIndexPairs) = 0; diff --git a/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp b/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp index a28e560d0..5f4725c69 100644 --- a/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp +++ b/shared/src/map/layers/tiled/vector/sublayers/background/Tiled2dMapVectorBackgroundSubLayer.cpp @@ -42,7 +42,7 @@ void Tiled2dMapVectorBackgroundSubLayer::onAdded(const std::shared_ptrstyle.getPattern(evalContext); if (!patternName.empty()) { - auto shader = mapInterface->getShaderFactory()->createPolygonPatternGroupShader(); + auto shader = mapInterface->getShaderFactory()->createPolygonPatternGroupShader(false); shader->asShaderProgramInterface()->setBlendMode(description->style.getBlendMode(evalContext)); diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.cpp index 36839614c..8fdbbfeab 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.cpp @@ -100,6 +100,16 @@ void Tiled2dMapVectorInteractionManager::clearTouch() { } } +void Tiled2dMapVectorInteractionManager::performClick(const Coord &coord) { + const auto lambda = [&coord](std::unordered_set &layers, auto &manager) -> bool { + if (auto strongManager = manager.lock()) { + return strongManager->performClick(layers, coord); + } + return false; + }; + callInReverseOrder(lambda); +} + template bool Tiled2dMapVectorInteractionManager::callInReverseOrder(F&& managerLambda) { if (!mapDescription) { diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.h b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.h index cc95dea9a..4912e138a 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.h +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorInteractionManager.h @@ -43,6 +43,8 @@ class Tiled2dMapVectorInteractionManager : public TouchInterface { void clearTouch() override; + void performClick(const Coord &coord); + private: template inline bool callInReverseOrder(F&& managerLambda); diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp index 6127fb1a9..39af8557f 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.cpp @@ -741,6 +741,20 @@ bool Tiled2dMapVectorSourceSymbolDataManager::onClickUnconfirmed(const std::unor } bool Tiled2dMapVectorSourceSymbolDataManager::onClickConfirmed(const std::unordered_set &layers, const Vec2F &posScreen) { + auto lockSelfPtr = shared_from_this(); + auto mapInterface = lockSelfPtr ? lockSelfPtr->mapInterface.lock() : nullptr; + auto camera = mapInterface ? mapInterface->getCamera() : nullptr; + auto conversionHelper = mapInterface ? mapInterface->getCoordinateConverterHelper() : nullptr; + if (!camera || !conversionHelper) { + return false; + } + + Coord clickCoords = camera->coordFromScreenPosition(posScreen); + + return performClick(layers, clickCoords); +} + +bool Tiled2dMapVectorSourceSymbolDataManager::performClick(const std::unordered_set &layers, const Coord &coord) { auto lockSelfPtr = shared_from_this(); auto mapInterface = lockSelfPtr ? lockSelfPtr->mapInterface.lock() : nullptr; auto camera = mapInterface ? mapInterface->getCamera() : nullptr; @@ -750,8 +764,7 @@ bool Tiled2dMapVectorSourceSymbolDataManager::onClickConfirmed(const std::unorde return false; } - Coord clickCoords = camera->coordFromScreenPosition(posScreen); - Coord clickCoordsRenderCoord = conversionHelper->convertToRenderSystem(clickCoords); + Coord clickCoordsRenderCoord = conversionHelper->convertToRenderSystem(coord); double clickPadding = camera->mapUnitsFromPixels(16); CircleD clickHitCircle(clickCoordsRenderCoord.x, clickCoordsRenderCoord.y, clickPadding); @@ -762,7 +775,7 @@ bool Tiled2dMapVectorSourceSymbolDataManager::onClickConfirmed(const std::unorde continue; } for (const auto &[layerIdentifier, symbolGroups] : symbolGroupsMap) { - if (interactableLayers.count(layerIdentifier) == 0) { + if (interactableLayers.find(layerIdentifier) == interactableLayers.end() || layers.find(layerIdentifier) == layers.end()) { continue; } for (const auto &symbolGroup : std::get<1>(symbolGroups)) { @@ -778,7 +791,6 @@ bool Tiled2dMapVectorSourceSymbolDataManager::onClickConfirmed(const std::unorde } } return false; - } bool Tiled2dMapVectorSourceSymbolDataManager::onDoubleClick(const std::unordered_set &layers, const Vec2F &posScreen) { diff --git a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.h b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.h index 3d55de154..04eff34b7 100644 --- a/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.h +++ b/shared/src/map/layers/tiled/vector/symbol/Tiled2dMapVectorSourceSymbolDataManager.h @@ -100,6 +100,8 @@ class Tiled2dMapVectorSourceSymbolDataManager: void clearTouch() override; + bool performClick(const std::unordered_set &layers, const Coord &coord) override; + void onSymbolGroupInitialized(bool success, const Tiled2dMapVersionedTileInfo &tileInfo, const std::string &layerIdentifier, const WeakActor &symbolGroup); void setSymbolDelegate(const /*not-null*/ std::shared_ptr & symbolDelegate); diff --git a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp index 380eed5a2..dbfbceada 100644 --- a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.cpp @@ -401,6 +401,17 @@ std::vector> Tiled2dMapVectorLineTile::ge } bool Tiled2dMapVectorLineTile::onClickConfirmed(const Vec2F &posScreen) { + const auto mapInterface = this->mapInterface.lock(); + const auto camera = mapInterface ? mapInterface->getCamera() : nullptr; + if (!camera) { + return false; + } + + auto point = camera->coordFromScreenPosition(posScreen); + return performClick(point); +} + +bool Tiled2dMapVectorLineTile::performClick(const Coord &coord) { const auto mapInterface = this->mapInterface.lock(); const auto camera = mapInterface ? mapInterface->getCamera() : nullptr; const auto coordinateConverter = mapInterface ? mapInterface->getCoordinateConverterHelper() : nullptr; @@ -409,7 +420,6 @@ bool Tiled2dMapVectorLineTile::onClickConfirmed(const Vec2F &posScreen) { return false; } - auto point = camera->coordFromScreenPosition(posScreen); double zoomIdentifier = layerConfig->getZoomIdentifier(camera->getZoom()); auto lineDescription = std::static_pointer_cast(description); @@ -418,10 +428,10 @@ bool Tiled2dMapVectorLineTile::onClickConfirmed(const Vec2F &posScreen) { for (auto const &[lineCoordinateVector, featureContext]: hitDetection) { for (auto const &coordinates: lineCoordinateVector) { auto lineWidth = lineDescription->style.getLineWidth(EvaluationContext(zoomIdentifier, dpFactor, featureContext, featureStateManager)); - if (LineHelper::pointWithin(coordinates, point, lineWidth, coordinateConverter)) { + if (LineHelper::pointWithin(coordinates, coord, lineWidth, coordinateConverter)) { if (multiselect) { featureInfos.push_back(featureContext->getFeatureInfo()); - } else if (strongSelectionDelegate->didSelectFeature(featureContext->getFeatureInfo(), description->identifier, point)) { + } else if (strongSelectionDelegate->didSelectFeature(featureContext->getFeatureInfo(), description->identifier, coord)) { return true; } } @@ -429,7 +439,7 @@ bool Tiled2dMapVectorLineTile::onClickConfirmed(const Vec2F &posScreen) { } if (multiselect && !featureInfos.empty()) { - return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, point); + return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, coord); } return false; diff --git a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h index 17f650d23..83c76e455 100644 --- a/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/line/Tiled2dMapVectorLineTile.h @@ -42,6 +42,8 @@ class Tiled2dMapVectorLineTile bool onClickConfirmed(const Vec2F &posScreen) override; + bool performClick(const Coord &coord) override; + private: void addLines(const std::vector, int>>>> &styleIdLinesVector); diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp index 728267b29..923f083b3 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.cpp @@ -28,7 +28,8 @@ Tiled2dMapVectorPolygonPatternTile::Tiled2dMapVectorPolygonPatternTile(const std const std::shared_ptr &spriteData, const std::shared_ptr &spriteTexture, const std::shared_ptr &featureStateManager) - : Tiled2dMapVectorTile(mapInterface, tileInfo, description, layerConfig, tileCallbackInterface, featureStateManager), spriteData(spriteData), spriteTexture(spriteTexture), usedKeys(description->getUsedKeys()) { + : Tiled2dMapVectorTile(mapInterface, tileInfo, description, layerConfig, tileCallbackInterface, featureStateManager), + spriteData(spriteData), spriteTexture(spriteTexture), usedKeys(description->getUsedKeys()), fadeInPattern(description->style.fadeInPattern) { isStyleZoomDependant = usedKeys.containsUsedKey(Tiled2dMapVectorStyleParser::zoomExpression); isStyleStateDependant = usedKeys.isStateDependant(); } @@ -202,7 +203,7 @@ void Tiled2dMapVectorPolygonPatternTile::setVectorTileData(const Tiled2dMapVecto } else { styleGroupIndex = (int) featureGroups.size(); styleIndex = 0; - auto shader = shaderFactory->createPolygonPatternGroupShader(); + auto shader = shaderFactory->createPolygonPatternGroupShader(fadeInPattern); auto polygonDescription = std::static_pointer_cast(description); shader->asShaderProgramInterface()->setBlendMode(polygonDescription->style.getBlendMode(EvaluationContext(0.0, dpFactor, std::make_shared(), featureStateManager))); shaders.push_back(shader); @@ -406,27 +407,35 @@ void Tiled2dMapVectorPolygonPatternTile::setupTextureCoordinates() { bool Tiled2dMapVectorPolygonPatternTile::onClickConfirmed(const Vec2F &posScreen) { auto mapInterface = this->mapInterface.lock(); auto camera = mapInterface ? mapInterface->getCamera() : nullptr; + if (!camera) { + return false; + } + auto point = camera->coordFromScreenPosition(posScreen); + return performClick(point); +} + +bool Tiled2dMapVectorPolygonPatternTile::performClick(const Coord &coord) { + auto mapInterface = this->mapInterface.lock(); auto converter = mapInterface ? mapInterface->getCoordinateConverterHelper() : nullptr; auto strongSelectionDelegate = selectionDelegate.lock(); - if (!camera || !strongSelectionDelegate || !converter) { + if (!strongSelectionDelegate || !converter) { return false; } - auto point = camera->coordFromScreenPosition(posScreen); std::vector featureInfos; for (auto const &[polygon, featureContext]: hitDetectionPolygons) { - if (VectorTileGeometryHandler::isPointInTriangulatedPolygon(point, polygon, converter)) { + if (VectorTileGeometryHandler::isPointInTriangulatedPolygon(coord, polygon, converter)) { if (multiselect) { featureInfos.push_back(featureContext->getFeatureInfo()); } else if (strongSelectionDelegate->didSelectFeature(featureContext->getFeatureInfo(), description->identifier, - converter->convert(CoordinateSystemIdentifiers::EPSG4326(),point))) { + converter->convert(CoordinateSystemIdentifiers::EPSG4326(),coord))) { return true; } } } if (multiselect && !featureInfos.empty()) { - return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, converter->convert(CoordinateSystemIdentifiers::EPSG4326(), point)); + return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, converter->convert(CoordinateSystemIdentifiers::EPSG4326(), coord)); } return false; diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h index 7e947dec6..586eb2d5e 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonPatternTile.h @@ -47,6 +47,8 @@ class Tiled2dMapVectorPolygonPatternTile bool onClickConfirmed(const Vec2F &posScreen) override; + bool performClick(const Coord &coord) override; + private: struct ObjectDescriptions { std::vector vertices; @@ -76,6 +78,8 @@ class Tiled2dMapVectorPolygonPatternTile std::optional lastZoom = std::nullopt; std::optional lastInZoomRange = std::nullopt; + bool fadeInPattern = false; + std::shared_ptr spriteData; std::shared_ptr spriteTexture; diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp index c29f131f3..6455578b4 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.cpp @@ -320,27 +320,35 @@ std::vector> Tiled2dMapVectorPolygonTile: bool Tiled2dMapVectorPolygonTile::onClickConfirmed(const Vec2F &posScreen) { auto mapInterface = this->mapInterface.lock(); auto camera = mapInterface ? mapInterface->getCamera() : nullptr; + if (!camera) { + return false; + } + auto point = camera->coordFromScreenPosition(posScreen); + return performClick(point); +} + +bool Tiled2dMapVectorPolygonTile::performClick(const Coord &coord) { + auto mapInterface = this->mapInterface.lock(); auto converter = mapInterface ? mapInterface->getCoordinateConverterHelper() : nullptr; auto strongSelectionDelegate = selectionDelegate.lock(); - if (!camera || !strongSelectionDelegate || !converter) { + if (!strongSelectionDelegate || !converter) { return false; } - auto point = camera->coordFromScreenPosition(posScreen); std::vector featureInfos; for (auto const &[polygon, featureContext]: hitDetectionPolygons) { - if (VectorTileGeometryHandler::isPointInTriangulatedPolygon(point, polygon, converter)) { + if (VectorTileGeometryHandler::isPointInTriangulatedPolygon(coord, polygon, converter)) { if (multiselect) { featureInfos.push_back(featureContext->getFeatureInfo()); } else if (strongSelectionDelegate->didSelectFeature(featureContext->getFeatureInfo(), description->identifier, - converter->convert(CoordinateSystemIdentifiers::EPSG4326(),point))) { + converter->convert(CoordinateSystemIdentifiers::EPSG4326(),coord))) { return true; } } } if (multiselect && !featureInfos.empty()) { - return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, converter->convert(CoordinateSystemIdentifiers::EPSG4326(), point)); + return strongSelectionDelegate->didMultiSelectLayerFeatures(featureInfos, description->identifier, converter->convert(CoordinateSystemIdentifiers::EPSG4326(), coord)); } return false; diff --git a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h index a1604063b..f92164c80 100644 --- a/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/polygon/Tiled2dMapVectorPolygonTile.h @@ -42,6 +42,8 @@ class Tiled2dMapVectorPolygonTile bool onClickConfirmed(const Vec2F &posScreen) override; + bool performClick(const Coord &coord) override; + private: struct ObjectDescriptions { diff --git a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp index d60b4b0f0..4d7a5ebc1 100644 --- a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp +++ b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.cpp @@ -150,3 +150,7 @@ void Tiled2dMapVectorRasterTile::setupTile(const Tiled2dMapVectorTileDataRaster std::vector> Tiled2dMapVectorRasterTile::generateRenderObjects() { return {tileObject->getRenderObject()}; } + +bool Tiled2dMapVectorRasterTile::performClick(const Coord &coord) { + return false; +} diff --git a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h index 91c72cc76..5b7407489 100644 --- a/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h +++ b/shared/src/map/layers/tiled/vector/tiles/raster/Tiled2dMapVectorRasterTile.h @@ -42,6 +42,8 @@ class Tiled2dMapVectorRasterTile : public Tiled2dMapVectorTile, public std::enab void setupTile(const Tiled2dMapVectorTileDataRaster tileData); + bool performClick(const Coord &coord) override; + private: std::shared_ptr tileObject; std::shared_ptr tileData;