Skip to content

Commit

Permalink
Add bent cable and shadow
Browse files Browse the repository at this point in the history
For #5
  • Loading branch information
svetter committed Jul 13, 2024
1 parent a17e18e commit aa73143
Show file tree
Hide file tree
Showing 5 changed files with 320 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.view.View
import androidx.core.content.ContextCompat
import kotlin.math.cos
import kotlin.math.roundToInt
import kotlin.math.sin
import kotlin.math.tan


Expand Down Expand Up @@ -48,8 +47,8 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
private var micVector: Drawable? = cardioidMicVector
private var micVectorMirrored: Drawable? = cardioidMicVectorMirrored
private val micShadowImage: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.mic_shadow)
private val cableVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable)
private val cableShadowImage: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable_shadow)
private val cableVector: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable_bent)
private val cableShadowImage: Drawable? = ContextCompat.getDrawable(context!!, R.drawable.cable_bent_shadow)


private val cmPerInch = 2.54f
Expand All @@ -66,8 +65,9 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
// Input graphics parameters
private val micWidthCm = 2f
private val micHeightCm = 8f
private val cableWidthCm = micWidthCm
private val cableHeightCm = 60f
private val cableWidthCm = 11f
private val cableHeightCm = 16.5f
private val cableCenterXCm = 1f
private val shadowOverhangCm = 1f
// Layout
private val shadowXOffsetCm = -0.5f
Expand Down Expand Up @@ -224,6 +224,7 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
val leftMicLeftX = leftMicCenterX - micWidth / 2
val rightMicCenterX = centerX + halfMicDistance
val rightMicLeftX = rightMicCenterX - micWidth / 2
val cableCenterX = cableCenterXCm * pixelPerCm

val micTopY = centerY - 1 * pixelPerCm
val micBottomY = micTopY + micHeight
Expand Down Expand Up @@ -281,31 +282,21 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
// Vary mirrored microphone alpha based on angle to simulate light reflections
micVectorMirrored?.alpha = (128 * (1 - cos(Math.toRadians(micAngle / 2.0)))).roundToInt()

// Vary cable alpha based on angle to avoid covering the lower microphone
cableVector?.alpha = when {
micAngle <= cableVisibleUntilDeg -> 255
micAngle >= cableInvisibleFromDeg -> 0
else -> {
val xScale = Math.PI / 2 / (cableInvisibleFromDeg - cableVisibleUntilDeg)
(255.0 * sin((cableInvisibleFromDeg - micAngle) * xScale)).roundToInt()
}
}
cableShadowImage?.alpha = cableVector?.let {
(it.alpha.toFloat() * maxShadowAlpha / 255f).roundToInt()
} ?: 0
val leftRotAngle = -micAngle / 2
val rightRotAngle = micAngle / 2
val leftCableCenterX = leftMicLeftX + cableCenterX
val rightCableCenterX = rightMicLeftX + cableCenterX

val leftRotAngle = -micAngle / 2
val rightRotAngle = micAngle / 2
// drawable leftX topY width height rotationAngle rotationCenterY
// drawable leftX topY width height rotationAngle rotationCenterX, rotationCenterY
// RIGHT
drawShadow (canvas, cableShadowImage, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rotationCenterY = centerY)
drawShadow (canvas, micShadowImage, rightMicLeftX, micTopY, micWidth, micHeight, rightRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rotationCenterY = centerY)
drawShadow (canvas, cableShadowImage, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, rotationCenterY = centerY)
drawShadow (canvas, micShadowImage, rightMicLeftX, micTopY, micWidth, micHeight, rightRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, rightMicLeftX, cableTopY, cableWidth, cableHeight, rightRotAngle, rightCableCenterX, centerY)
drawMic (canvas, rightNotLeft = true, rightMicLeftX, micTopY)
// LEFT
drawShadow (canvas, cableShadowImage, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, rotationCenterY = centerY)
drawShadow (canvas, micShadowImage, leftMicLeftX, micTopY, micWidth, micHeight, leftRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, rotationCenterY = centerY)
drawShadow (canvas, cableShadowImage, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawShadow (canvas, micShadowImage, leftMicLeftX, micTopY, micWidth, micHeight, leftRotAngle, rotationCenterY = centerY)
draw (canvas, cableVector, leftMicLeftX, cableTopY, cableWidth, cableHeight, leftRotAngle, leftCableCenterX, rotationCenterY = centerY, scaleX = -1f)
drawMic (canvas, rightNotLeft = false, leftMicLeftX, micTopY)
}

Expand Down Expand Up @@ -607,12 +598,14 @@ class StereoConfigView(context: Context?, attrs: AttributeSet?) : View(context,
casterHeight: Float,
rotationAngle: Float = 0f,
rotationCenterX: Float = casterLeftX + casterWidth / 2,
rotationCenterY: Float = casterTopY + casterHeight / 2
rotationCenterY: Float = casterTopY + casterHeight / 2,
scaleX: Float = 1f,
scaleY: Float = 1f
) = draw(
canvas, drawable,
casterLeftX - shadowOverhang, casterTopY - shadowOverhang,
casterWidth + 2 * shadowOverhang, casterHeight + 2 * shadowOverhang,
rotationAngle, rotationCenterX, rotationCenterY, shadowXOffset, shadowYOffset
rotationAngle, rotationCenterX, rotationCenterY, shadowXOffset, shadowYOffset, scaleX, scaleY
)


Expand Down
168 changes: 168 additions & 0 deletions app/src/main/res/drawable/cable_bent.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="110dp"
android:height="165dp"
android:viewportWidth="1100"
android:viewportHeight="1650">
<path
android:pathData="M1100,1580A1000,1000 0,0 1,392.9 1287.1,1000 1000,0 0,1 100,580"
android:strokeLineJoin="round"
android:strokeWidth="50"
android:fillColor="#00000000">
<aapt:attr name="android:strokeColor">
<gradient
android:centerX="1100"
android:centerY="580"
android:gradientRadius="1024.8"
android:type="radial">
<item android:offset="0.95143855" android:color="#FF090909"/>
<item android:offset="0.9598496" android:color="#FF7B7B7B"/>
<item android:offset="0.96453476" android:color="#FF7D7D7D"/>
<item android:offset="0.97134894" android:color="#FF1D1D1D"/>
<item android:offset="0.98377508" android:color="#FF161616"/>
<item android:offset="0.98873448" android:color="#FF4C4C4C"/>
<item android:offset="0.99368465" android:color="#FF4B4B4B"/>
<item android:offset="0.99609345" android:color="#FF161616"/>
<item android:offset="1" android:color="#FF0F0F0F"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M1100,1580A1000,1000 0,0 1,392.9 1287.1,1000 1000,0 0,1 100,580"
android:strokeLineJoin="round"
android:strokeWidth="50"
android:fillColor="#00000000"
android:strokeColor="#00000000">
</path>
<path
android:pathData="M20,-150h160v375h-160z"
android:strokeLineJoin="round"
android:strokeWidth="6.23049"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="20"
android:startY="37.5"
android:endX="180"
android:endY="37.5"
android:type="linear">
<item android:offset="0" android:color="#FF070707"/>
<item android:offset="0.04734848" android:color="#FF1F1F1F"/>
<item android:offset="0.10039726" android:color="#FF858585"/>
<item android:offset="0.17586844" android:color="#FF808080"/>
<item android:offset="0.24110308" android:color="#FF111111"/>
<item android:offset="0.63068181" android:color="#FF262626"/>
<item android:offset="0.69886363" android:color="#FF999999"/>
<item android:offset="0.8125" android:color="#FF999999"/>
<item android:offset="0.86363631" android:color="#FF2F2F2F"/>
<item android:offset="1" android:color="#FF0E0E0E"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m19.5,220c-2.7,-0 -4.7,1.8 -4.5,5.5l9.1,159.4c0.2,2.8 2.5,5.1 5.3,5.1h0.6v20c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.1,6.7 -10.1,6.7v5c0,3.3 1.7,5 5,5h60v-360z"
android:strokeLineJoin="miter"
android:strokeWidth="2.64462"
android:strokeColor="#00000000"
android:strokeLineCap="butt">
<aapt:attr name="android:fillColor">
<gradient
android:startX="99.4"
android:startY="580.8"
android:endX="50.9"
android:endY="584.8"
android:type="linear">
<item android:offset="0.2" android:color="#FF252525"/>
<item android:offset="0.6" android:color="#FF7D7D7D"/>
<item android:offset="0.9" android:color="#FF262626"/>
<item android:offset="1" android:color="#FF161616"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m180.5,220c2.7,-0 4.7,1.8 4.5,5.5l-9.1,159.4c-0.2,2.8 -2.5,5.1 -5.3,5.1h-0.6v20c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.2,6.7 10.2,6.7l-0.6,5.9c0,0 -8.9,1.8 -11.3,5.1 -1.1,1.6 -1.4,4.1 -0.6,5.9 1.8,3.7 10.1,6.7 10.1,6.7 0,0 0,1.7 0,5 0,3.3 -1.7,5 -5,5 -16.7,0 -33.3,0 -50,0v-360z"
android:strokeLineJoin="miter"
android:strokeWidth="2.64462"
android:strokeColor="#00000000"
android:strokeLineCap="butt">
<aapt:attr name="android:fillColor">
<gradient
android:startX="100.6"
android:startY="580.8"
android:endX="148.9"
android:endY="584.2"
android:type="linear">
<item android:offset="0" android:color="#FF252525"/>
<item android:offset="0.4" android:color="#FF7D7D7D"/>
<item android:offset="0.7" android:color="#FF262626"/>
<item android:offset="1" android:color="#FF161616"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m19.5,220c-2.7,-0 -4.7,1.8 -4.5,5.5l9.1,159.4c0.2,2.8 2.5,5.1 5.3,5.1h0.6v20c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.5,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.2,6.7 -10.2,6.7l0.6,5.9c0,0 8.9,1.8 11.3,5.1 1.1,1.6 1.4,4.1 0.6,5.9 -1.8,3.7 -10.1,6.7 -10.1,6.7v5c0,3.3 1.7,5 5,5 33.3,0 66.7,0 100,0 3.3,0 5,-1.7 5,-5v-5c0,0 -8.3,-3 -10.1,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.6,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.6,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.6,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.5,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.5,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.5,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1l0.6,-5.9c0,0 -8.4,-3 -10.2,-6.7 -0.9,-1.8 -0.6,-4.3 0.6,-5.9 2.4,-3.4 11.3,-5.1 11.3,-5.1v-20h0.6c2.8,-0 5,-2.3 5.3,-5.1l9.1,-159.4c0.2,-3.7 -1.8,-5.5 -4.5,-5.5 -53.7,0 -107.4,0 -161,0z"
android:strokeLineJoin="miter"
android:strokeWidth="2.64462"
android:strokeColor="#00000000"
android:strokeLineCap="butt">
<aapt:attr name="android:fillColor">
<gradient
android:startX="100"
android:startY="220"
android:endX="100"
android:endY="580"
android:type="linear">
<item android:offset="0" android:color="#D7000000"/>
<item android:offset="0.02263649" android:color="#00000000"/>
<item android:offset="0.44946402" android:color="#00000000"/>
<item android:offset="0.4675988" android:color="#D9000000"/>
<item android:offset="0.47521508" android:color="#4C000000"/>
<item android:offset="0.48565084" android:color="#00000000"/>
<item android:offset="0.52063912" android:color="#00000000"/>
<item android:offset="0.52881193" android:color="#E5060606"/>
<item android:offset="0.55425769" android:color="#00000000"/>
<item android:offset="0.56285942" android:color="#00000000"/>
<item android:offset="0.57371563" android:color="#B3000000"/>
<item android:offset="0.57689399" android:color="#00000000"/>
<item android:offset="0.59170443" android:color="#00000000"/>
<item android:offset="0.5950374" android:color="#E5000000"/>
<item android:offset="0.62134451" android:color="#00000000"/>
<item android:offset="0.62709957" android:color="#00000000"/>
<item android:offset="0.6399833" android:color="#B2000000"/>
<item android:offset="0.64273417" android:color="#00000000"/>
<item android:offset="0.65723944" android:color="#00000000"/>
<item android:offset="0.66018945" android:color="#E4000000"/>
<item android:offset="0.68696409" android:color="#00000000"/>
<item android:offset="0.69288719" android:color="#00000000"/>
<item android:offset="0.70535761" android:color="#B2000000"/>
<item android:offset="0.70771337" android:color="#00000000"/>
<item android:offset="0.72310728" android:color="#00000000"/>
<item android:offset="0.72571307" android:color="#E5000000"/>
<item android:offset="0.75081825" android:color="#00000000"/>
<item android:offset="0.75778812" android:color="#00000000"/>
<item android:offset="0.77115053" android:color="#B1000000"/>
<item android:offset="0.77317518" android:color="#00000000"/>
<item android:offset="0.78807515" android:color="#00000000"/>
<item android:offset="0.79155731" android:color="#E6000000"/>
<item android:offset="0.81697446" android:color="#00000000"/>
<item android:offset="0.82185042" android:color="#00000000"/>
<item android:offset="0.83593553" android:color="#B2000000"/>
<item android:offset="0.83837211" android:color="#00000000"/>
<item android:offset="0.85400206" android:color="#00000000"/>
<item android:offset="0.85709494" android:color="#E5000000"/>
<item android:offset="0.88242334" android:color="#00000000"/>
<item android:offset="0.88761991" android:color="#00000000"/>
<item android:offset="0.90285093" android:color="#B1000000"/>
<item android:offset="0.90593898" android:color="#00000000"/>
<item android:offset="0.91937774" android:color="#00000000"/>
<item android:offset="0.92295063" android:color="#E4000000"/>
<item android:offset="0.95111746" android:color="#00000000"/>
<item android:offset="0.95590591" android:color="#00000000"/>
<item android:offset="0.96959233" android:color="#B1000000"/>
<item android:offset="0.97187108" android:color="#00000000"/>
<item android:offset="0.98637807" android:color="#00000000"/>
<item android:offset="0.99812031" android:color="#D8000000"/>
</gradient>
</aapt:attr>
</path>
</vector>
Binary file added app/src/main/res/drawable/cable_bent_shadow.webp
Binary file not shown.
Loading

0 comments on commit aa73143

Please sign in to comment.