comments pt1
This commit is contained in:
@@ -369,6 +369,15 @@ class BowlingCameraActivity : AppCompatActivity(), CameraXController.Callback {
|
||||
debugSessionLogger.stop()
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Advances the step index and updates the step button label.
|
||||
*
|
||||
* This method increments the current step index, cycling back to zero
|
||||
* once the end of the [stepLabels] list is reached. It then updates the
|
||||
* `btnShowStep` text to reflect the new step, ensuring the UI button
|
||||
* always displays the correct label for the current position in the
|
||||
* sequence.
|
||||
*/
|
||||
fun onStepIncrease() {
|
||||
currentStepIndex = (currentStepIndex + 1) % stepLabels.size
|
||||
binding.btnShowStep.setText(stepLabels[currentStepIndex])
|
||||
|
||||
@@ -39,6 +39,8 @@ import com.example.jnicpp.R
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
import com.google.mlkit.vision.pose.PoseLandmark // for testing
|
||||
|
||||
/**
|
||||
* @brief Owns all CameraX use-case binding and recording control.
|
||||
*
|
||||
@@ -271,7 +273,18 @@ class CameraXController(
|
||||
mirror = frame.isMirroring
|
||||
)
|
||||
PoseSkeletonRenderer.draw(canvas, poseFrame.landmarks, transform, overlayBonePaint, overlayJointPaint)
|
||||
feedbackUI?.drawCircles(canvas, poseFrame.landmarks, transform, true)
|
||||
|
||||
// currentLandmarks to change to landmarks that require highlighting
|
||||
// test code to contain only left wrist in currentLandmarks to not clutter the screen
|
||||
val leftWrist = poseFrame.landmarks[PoseLandmark.LEFT_WRIST]
|
||||
|
||||
// Build a single‑item map if it exists
|
||||
val singleLandmark = if (leftWrist != null) {
|
||||
mapOf(PoseLandmark.LEFT_WRIST to leftWrist)
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
feedbackUI?.drawCircles(canvas, singleLandmark, transform, true)
|
||||
feedbackUI?.showBanner(canvas, "Body too upright, take a larger 1st step", true)
|
||||
}
|
||||
true
|
||||
|
||||
@@ -62,6 +62,18 @@ class FeedbackUI(private val context: Context, private val rootView: View) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays a banner with the given message on the provided canvas.
|
||||
*
|
||||
* The banner is centered horizontally and offset vertically. It uses
|
||||
* `StaticLayout` to support multi-line text and scales its size depending
|
||||
* on whether the canvas is for live UI or recording output.
|
||||
*
|
||||
* @param canvas The canvas to draw the banner on.
|
||||
* @param message The text message to display inside the banner.
|
||||
* @param forRecord If true, scales the banner relative to recording canvas
|
||||
* dimensions; otherwise uses live UI scale.
|
||||
*/
|
||||
fun showBanner(canvas: Canvas, message: String, forRecord: Boolean = false) {
|
||||
val scale = if (forRecord) computeCamScale(canvas) else 1f
|
||||
val paddingX = bannerPaddingX * scale
|
||||
@@ -104,6 +116,19 @@ class FeedbackUI(private val context: Context, private val rootView: View) {
|
||||
canvas.restore()
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draws glowing circles around all provided landmarks.
|
||||
*
|
||||
* Each landmark’s coordinates are transformed by the given matrix before
|
||||
* drawing. Circles are rendered with both a white stroke and a red glow
|
||||
* effect for visibility.
|
||||
*
|
||||
* @param canvas The canvas to draw circles on.
|
||||
* @param landmarks A map of landmark indices to smoothed landmark positions.
|
||||
* @param transform A matrix applied to landmark coordinates before drawing.
|
||||
* @param forRecord If true, scales circle radius and stroke width for
|
||||
* recording output.
|
||||
*/
|
||||
// --- Shape overlay (circle) ---
|
||||
fun drawCircles(canvas: Canvas, landmarks: Map<Int, SmoothedLandmark>, transform: Matrix, forRecord: Boolean = false) {
|
||||
for (landmark in landmarks.values) {
|
||||
@@ -113,6 +138,22 @@ class FeedbackUI(private val context: Context, private val rootView: View) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Draws a single circle with both a solid stroke and a glowing outline.
|
||||
*
|
||||
* This method renders a circle at the specified coordinates using two
|
||||
* layered paints: a white stroke (`circlePaint`) and a red glow (`glowPaint`).
|
||||
* The radius and stroke widths are scaled depending on whether the canvas
|
||||
* is for live UI or recording output, ensuring consistent visual feedback
|
||||
* across different resolutions.
|
||||
*
|
||||
* @param canvas The canvas to draw the circle on.
|
||||
* @param x The x‑coordinate of the circle’s center.
|
||||
* @param y The y‑coordinate of the circle’s center.
|
||||
* @param radius The circle radius. If set to 0, defaults to [CIRCLE_RADIUS].
|
||||
* @param forRecord If true, applies recording scale factor to radius and
|
||||
* stroke width; otherwise uses live UI scale.
|
||||
*/
|
||||
fun drawCircle(canvas: Canvas, x: Float, y: Float, radius: Float = 0f, forRecord: Boolean = false) {
|
||||
val scale = if (forRecord) camScale else 1f
|
||||
|
||||
@@ -123,13 +164,29 @@ class FeedbackUI(private val context: Context, private val rootView: View) {
|
||||
canvas.drawCircle(x, y, rad, glowPaint)
|
||||
}
|
||||
|
||||
// Store live UI size once
|
||||
/**
|
||||
* @brief Updates stored live UI dimensions based on the root view.
|
||||
*
|
||||
* This method caches the width and height of the root view so that
|
||||
* recording canvas scaling can be computed consistently later.
|
||||
*
|
||||
* @param rootView The root view whose dimensions are measured.
|
||||
*/
|
||||
fun setLiveUiSize(rootView: View) {
|
||||
liveUiWidth = rootView.width
|
||||
liveUiHeight = rootView.height
|
||||
}
|
||||
|
||||
// Compute scale when drawing to recording canvas
|
||||
/**
|
||||
* @brief Computes the scaling factor between live UI and recording canvas.
|
||||
*
|
||||
* The scale is determined by comparing the recording canvas dimensions
|
||||
* against the cached live UI dimensions, using the smaller ratio to
|
||||
* preserve aspect consistency.
|
||||
*
|
||||
* @param recordCanvas The canvas used for recording output.
|
||||
* @return A float scale factor to apply when drawing to the recording canvas.
|
||||
*/
|
||||
private fun computeCamScale(recordCanvas: Canvas): Float {
|
||||
if (liveUiWidth == 0 || liveUiHeight == 0) return 1f
|
||||
val scaleX = recordCanvas.width.toFloat() / liveUiWidth.toFloat()
|
||||
|
||||
@@ -144,6 +144,16 @@ class PoseOverlayView @JvmOverloads constructor(
|
||||
feedbackUI?.showBanner(canvas, "Body too upright, take a larger 1st step efsdfdg d dg df gdgdfg df ")
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attaches a FeedbackUI instance to this component.
|
||||
*
|
||||
* This method stores a reference to the provided [FeedbackUI] so that
|
||||
* banner rendering and landmark overlays can be delegated to it. By
|
||||
* attaching the UI handler here, the parent component gains access to
|
||||
* feedback drawing utilities without needing to manage them directly.
|
||||
*
|
||||
* @param feedbackUI The [FeedbackUI] instance to associate with this component.
|
||||
*/
|
||||
fun attachFeedback(feedbackUI: FeedbackUI) {
|
||||
this.feedbackUI = feedbackUI
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user