Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import de.westnordost.streetcomplete.quests.internet_access.AddInternetAccess
import de.westnordost.streetcomplete.quests.kerb_height.AddKerbHeight
import de.westnordost.streetcomplete.quests.lamp_type.AddLampType
import de.westnordost.streetcomplete.quests.lamp_mount.AddLampMount
import de.westnordost.streetcomplete.quests.direction.AddDirection
import de.westnordost.streetcomplete.quests.lanes.AddLanes
import de.westnordost.streetcomplete.quests.leaf_detail.AddForestLeafType
import de.westnordost.streetcomplete.quests.leaf_detail.AddTreeLeafType
Expand Down Expand Up @@ -656,6 +657,7 @@ fun getQuestTypeList(
EE_QUEST_OFFSET + 54 to AddLampType(),
EE_QUEST_OFFSET + 55 to AddPostOfficeType(),
EE_QUEST_OFFSET + 57 to AddLampMount(),
EE_QUEST_OFFSET + 58 to AddDirection(),
EE_QUEST_OFFSET + 10 to OsmoseQuest(osmoseDao),
EE_QUEST_OFFSET + 11 to CustomQuest(customQuestList),
// POI quests
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package de.westnordost.streetcomplete.quests.direction

import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.data.osm.geometry.ElementGeometry
import de.westnordost.streetcomplete.data.osm.osmquests.OsmFilterQuestType
import de.westnordost.streetcomplete.osm.Tags

class AddDirection : OsmFilterQuestType<Int>() {

override val elementFilter = """
nodes with (
amenity = bench
or advertising = billboard
or highway = traffic_sign
or amenity = vending_machine
or traffic_sign
)
and !direction
"""
override val changesetComment = "Specify direction object is facing"
override val wikiLink = "Key:direction"
override val icon = R.drawable.ic_quest_direction
override val defaultDisabledMessage: Int = R.string.default_disabled_msg_ee

override fun getTitle(tags: Map<String, String>) = R.string.quest_direction_title

override fun createForm() = AddDirectionForm()

override fun applyAnswerTo(answer: Int, tags: Tags, geometry: ElementGeometry, timestampEdited: Long) {
tags["direction"] = answer.toString()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package de.westnordost.streetcomplete.quests.direction

import android.os.Bundle
import android.view.View
import androidx.compose.material.Surface
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import de.westnordost.streetcomplete.databinding.ComposeViewBinding
import de.westnordost.streetcomplete.quests.AbstractOsmQuestForm
import de.westnordost.streetcomplete.screens.main.bottom_sheet.IsMapOrientationAware
import de.westnordost.streetcomplete.ui.util.content
import de.westnordost.streetcomplete.util.math.normalizeDegrees

class AddDirectionForm : AbstractOsmQuestForm<Int>(), IsMapOrientationAware {

override val contentLayoutResId = de.westnordost.streetcomplete.R.layout.compose_view
private val binding by contentViewBinding(ComposeViewBinding::bind)

private lateinit var direction: MutableState<Int>
private lateinit var mapRotation: MutableState<Float>

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.composeViewBase.content {
direction = rememberSaveable { mutableStateOf(0) }
mapRotation = remember { mutableStateOf(0f) }
Surface {
DirectionPicker(
mapRotation = mapRotation.value,
angle = mapRotation.value + direction.value,
onAngleChange = { direction.value = (it - mapRotation.value).toInt() },
)
}
}
checkIsFormComplete()
}

override fun onMapOrientation(rotation: Double, tilt: Double) {
mapRotation.value = -rotation.toFloat()
}

override fun onClickOk() {
applyAnswer(normalizeDegrees(direction.value.toFloat()).toInt())
}

override fun isFormComplete() = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package de.westnordost.streetcomplete.quests.direction

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import de.westnordost.streetcomplete.R
import de.westnordost.streetcomplete.util.math.normalizeDegrees
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.roundToInt
import kotlin.math.sin

@Composable
fun DirectionPicker(
mapRotation: Float,
angle: Float,
onAngleChange: (Int) -> Unit,
Comment on lines +30 to +31
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

angle is float, but onAngleChange is int?

Also, it is a bit of a problem that angle can not be null. That means, that before even taping any direction, the quest form will report that the form is complete. IIRC this is not standard, the OK button should only appear after the user input something.
A suggestion: either don't display the arrow at all at the beginning or as a sort of hint (with high transparency).

(This widget also probably needs some sort of usage hint. Like e.g. the street side select has: Maybe you can launch an effect on first opening that shows some kind of touch/ripple effect on the widget?)

modifier: Modifier = Modifier,
diameter: Dp = 200.dp
) {
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) {
Box(
modifier = Modifier
.size(diameter)
.graphicsLayer { rotationZ = mapRotation }
.pointerInput(mapRotation) {
detectDragGestures { change, _ ->
val center = Offset(size.width / 2f, size.height / 2f)
val dx = change.position.x - center.x
val dy = center.y - change.position.y
var deg = Math.toDegrees(atan2(dx.toDouble(), dy.toDouble())).toFloat()
deg = normalizeDegrees(deg + mapRotation)
val snapped = (deg / 5f).roundToInt() * 5
onAngleChange(((snapped % 360) + 360) % 360)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's that? Do you want to make sure that the returned angle is positive? You could use normalizeDegrees

}
}
) {
val lineColor = MaterialTheme.colors.onSurface
Canvas(modifier = Modifier.fillMaxSize()) {
val r = size.minDimension / 2f
val center = Offset(size.width / 2f, size.height / 2f)
for (i in 0 until 360 step 5) {
val rad = Math.toRadians((i - 90).toDouble())
val outer = Offset(
center.x + cos(rad).toFloat() * r,
center.y + sin(rad).toFloat() * r
)
val innerR = if (i % 30 == 0) r * 0.75f else r * 0.85f
val inner = Offset(
center.x + cos(rad).toFloat() * innerR,
center.y + sin(rad).toFloat() * innerR
)
drawLine(
color = lineColor,
start = inner,
end = outer,
strokeWidth = if (i % 30 == 0) 3f else 1f
)
}
}
androidx.compose.foundation.Image(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

y no import?

painter = painterResource(R.drawable.ic_direction_pointer_48dp),
contentDescription = null,
modifier = Modifier
.align(Alignment.Center)
.size(diameter * 0.6f)
.graphicsLayer { rotationZ = angle.toFloat() - mapRotation }
)
}
Text(text = "${normalizeDegrees(angle.toFloat() - mapRotation).toInt()}°")
}
}

3 changes: 3 additions & 0 deletions app/src/androidMain/res/values/strings_ee.xml
Original file line number Diff line number Diff line change
Expand Up @@ -804,4 +804,7 @@ Out of the box SCEE is configured to behave very similar to StreetComplete.</str
<string name="quest_material_bamboo">Bamboo</string>
<string name="quest_material_adobe">Adobe</string>

<!-- direction quest -->
<string name="quest_direction_title">Which direction is this facing?</string>

</resources>
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/ic_direction_pointer_48dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:viewportHeight="24" android:viewportWidth="24" android:width="48dp">

<path android:fillColor="#ff6600" android:pathData="M5.584,12.457H18.382" android:strokeColor="#ff6600" android:strokeLineCap="butt" android:strokeLineJoin="miter" android:strokeWidth="0.996116"/>

<path android:fillColor="#ff6600" android:pathData="M11.853,12.408V0.892" android:strokeColor="#ff6600" android:strokeLineCap="butt" android:strokeLineJoin="miter" android:strokeWidth="0.293291"/>

<path android:fillColor="#00000000" android:pathData="M11.853,12.408V3.624" android:strokeColor="#ff6600" android:strokeLineCap="butt" android:strokeLineJoin="miter" android:strokeWidth="1"/>

<path android:fillColor="#ff6600" android:pathData="m11.853,3.624h-1.535l1.573,-2.623 1.634,2.626z" android:strokeColor="#ff6600" android:strokeLineCap="butt" android:strokeLineJoin="miter" android:strokeWidth="1"/>

</vector>
16 changes: 16 additions & 0 deletions app/src/main/res/drawable/ic_quest_direction.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m128,64c0,35.35 -28.65,64 -64,64s-64,-28.65 -64,-64 28.65,-64 64,-64 64,28.65 64,64"
android:strokeWidth=".2"
android:fillColor="#9bbe55"/>
<path
android:pathData="M102.01,27.98 L46.72,45.53L57.27,56.38A10.81,10.81 92.35,0 1,72.55 56.6,10.81 10.81,92.35 0,1 72.33,71.89L82.87,82.74Z"
android:fillColor="#cc0000"/>
<path
android:pathData="M27.59,100.28 L46.72,45.53L57.27,56.38A10.81,10.81 92.35,0 0,57.05 71.67,10.81 10.81,92.35 0,0 72.33,71.89L82.87,82.74Z"
android:fillColor="#f4f2f3"/>
</vector>
112 changes: 112 additions & 0 deletions res/graphics/direction/direction_pointer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading