/// <summary>Render this AParentSceneNode by rendering all its children.</summary> protected override void DoRender( Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view, Transform parentTransform, int depth) { Transform combinedTransform = parentTransform.CombineWith(LocalTransform); if (view == HolofunkView.Secondary && SecondaryViewOption == SecondaryViewOption.PositionMirrored) { combinedTransform = new Transform( new Vector2( spriteBatch.Viewport.X - combinedTransform.Translation.X, combinedTransform.Translation.Y), combinedTransform.Scale); } Spam.Graphics.WriteLine(new string(' ', depth * 4) + Label + ": parentTransform " + parentTransform + ", localTransform " + LocalTransform + ", combinedTransform " + combinedTransform); // m_children must only be enumerated / mutated under lock (this) lock (this) { m_childSnapshot.AddRange(m_children); } for (int i = 0; i < m_childSnapshot.Count; i++) { m_childSnapshot[i].Render(now, graphicsDevice, spriteBatch, content, view, combinedTransform, depth + 1); } // note that clearing preserves the capacity in the list, so no reallocation on next render m_childSnapshot.Clear(); }
public void Render(Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view) { if (RootNode != null) { RootNode.Render(now, graphicsDevice, spriteBatch, content, view, Transform.Identity, 0); } Spam.Graphics.WriteLine("End Render"); }
protected override void DoRender( Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view, Transform parentTransform, int depth) { bool positionMirrored = SecondaryViewOption == SecondaryViewOption.PositionMirrored && view == HolofunkView.Secondary; Vector2 p0 = m_p0 + parentTransform.Translation; Vector2 p1 = m_p1 + parentTransform.Translation; if (positionMirrored) { p0 = new Vector2(spriteBatch.Viewport.X - p0.X, p0.Y); p1 = new Vector2(spriteBatch.Viewport.X - p1.X, p1.Y); } Vector2 diff = Vector2.Subtract(p1, p0); float angleRadians = (float)Math.Atan2(diff.Y, diff.X); float length = (float)Math.Sqrt(diff.X * diff.X + diff.Y * diff.Y) / 2; // Use NonPremultiplied, as our sprite textures are not premultiplied spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied); spriteBatch.Draw( content.TinyDot, p0, null, Color, angleRadians, new Vector2(0f, 1f), // we pivot around the center of the left edge of the 2x2 square new Vector2(length, LocalTransform.Scale.Y), SpriteEffects.None, 0); spriteBatch.End(); }
public void Update(Moment now) { // what is our track length? Duration<Sample> duration = m_trackLengthFunc(); Moment length = now.Clock.Time((int)duration); m_totalBeats = length.CompleteBeats; if (m_totalBeats == 0) { // there is no actual track duration here; we do nothing return; } // must be an exact number of beats //HoloDebug.Assert(length.TimepointsSinceLastBeat == 0); // what beat are we actually on now? long nowBeat = now.CompleteBeats; // what beat did we start at? int initialBeat = m_initialBeatFunc(); // if we got a -1 for initial beat, we also don't really exist // (this is a bit of a sleazy way to handle the ASIO race condition that exists // because ASIO may change state between m_trackLengthFunc() and m_initialBeatFunc()) if (initialBeat == -1) { m_totalBeats = 0; return; } // how many beats is that from when we started recording? long beatsSinceTrackStart = nowBeat - initialBeat; // what is that modulo our number of beats? m_currentBeat = beatsSinceTrackStart % m_totalBeats; m_fractionalBeat = now.FractionalBeat; if (m_fractionalBeat < 0) { m_fractionalBeat = 0; // within epsilon } HoloDebug.Assert(m_fractionalBeat < 1); }
internal void Update( PlayerHandModel playerModel, HolofunKinect kinect, Moment now) { m_parent.Update(playerModel, kinect, now); bool isDragging = m_model.DragStartLocation.HasValue; Color color = isDragging ? Color.White : new Color(0, 0, 0, 0); // cut alpha of bounding circle m_boundingCircleNode.Color = color * 0.5f; m_effectKnobLineNode.Color = color; m_effectKnobNode.Color = color; if (isDragging) { m_boundingCircleNode.LocalTransform = new Transform(m_model.DragStartLocation.Value, m_boundingCircleNode.LocalTransform.Scale); m_effectKnobLineNode.SetEndpoints(m_model.DragStartLocation.Value, m_model.CurrentKnobLocation.Value); m_effectKnobNode.LocalTransform = new Transform(m_model.CurrentKnobLocation.Value, m_effectKnobNode.LocalTransform.Scale); // TODO: this is a bit inefficient and hacky m_parent.ShowEffectLabels(PlayerEffectSpaceModel.EffectSettings[playerModel.EffectPresetIndex], now); } }
protected override void DoRender( Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view, Transform parentTransform, int depth) { Transform combinedTransform = parentTransform.CombineWith(LocalTransform); spriteBatch.Begin(); Vector2 textSize = content.SpriteFont.MeasureString(m_text); Vector2 origin = Vector2.Zero; if (Alignment == Alignment.Centered) { origin = textSize / 2; } else if (Alignment == Alignment.TopRight) { origin = new Vector2(textSize.X, 0); } spriteBatch.DrawString( content.SpriteFont, m_text, combinedTransform.Translation, Color, Rotation, origin, combinedTransform.Scale.X, SpriteEffects.None, 0); spriteBatch.End(); }
internal void Update(Moment now, bool touched, Color playerColor) { m_soundNode.LocalTransform = new Transform( m_soundNode.LocalTransform.Translation, new Vector2(MagicNumbers.LoopieScale) * m_levelRatioFunc()); m_soundNode.Color = m_circleColorFunc(); m_videoNode.LocalTransform = new Transform( m_videoNode.LocalTransform.Translation, new Vector2(MagicNumbers.HeadRatio) * (0.6f + m_levelRatioFunc() * 0.15f)); m_videoNode.Color = touched ? (playerColor * (m_videoColorFunc().A / 0xFF)) : m_videoColorFunc(); m_selectNode.LocalTransform = new Transform( m_soundNode.LocalTransform.Translation, new Vector2(MagicNumbers.LoopieScale)); m_selectNode.Color = touched ? new Color(playerColor.R >> 1, playerColor.G >> 1, playerColor.B >> 1, (byte)0xA0) : new Color(0, 0, 0, 0); m_beatNode.Update(now); }
/// <summary>The user's dragged the knob; update the effects appropriately.</summary> void RecalculateDragEffect(Moment now, Vector2 knobDelta) { // First, we want to map knobDelta -- that is effectively a vector to the bounding circle -- // to be a vector to the unit square. Vector2 normalizedDelta = knobDelta; normalizedDelta.Normalize(); // Now we want to find the longest dimension of normalizedDelta, and increase it to 1. float longestDimension = Math.Max(Math.Abs(normalizedDelta.X), Math.Abs(normalizedDelta.Y)); if (longestDimension < 0.0001f) { // might as well just be zero, so leave normalizedDelta alone } else { float longestDimensionMultiplier = 1 / longestDimension; // Scaling a vector does not change its angle. normalizedDelta *= longestDimensionMultiplier; } // Now normalizedDelta is effectively the vector to the unit square! Leave a little epsilon at the limit... HoloDebug.Assert(Math.Abs(normalizedDelta.X) <= 1.0001f); HoloDebug.Assert(Math.Abs(normalizedDelta.Y) <= 1.0001f); // Finally, the vector we really want is normalizedDelta multiplied by // knobDelta's length divided by the circle's radius. float lengthFraction = knobDelta.Length() / BoundingCircleRadius; Vector2 actualDelta = normalizedDelta * lengthFraction; Spam.Model.WriteLine("normalizedDelta: (" + normalizedDelta.X + ", " + normalizedDelta.Y + "); lengthFraction " + lengthFraction + "; actualDelta: (" + actualDelta.X + ", " + actualDelta.Y + ")"); // OK, now we have our X and Y values. Figure out which we are going to apply. ParameterMap vertical = normalizedDelta.Y < 0 ? m_effectSettings.Up : m_effectSettings.Down; ParameterMap horizontal = normalizedDelta.X < 0 ? m_effectSettings.Left : m_effectSettings.Right; foreach (Parameter p in vertical) { DragParameter(now, horizontal, p, Math.Abs(actualDelta.Y)); } foreach (Parameter p in horizontal) { DragParameter(now, null, p, Math.Abs(actualDelta.X)); } }
void DragParameter(Moment now, ParameterMap other, Parameter p, float value) { // We have a tiny gutter around 0, since some effects have a sharp step from 0 to anything else and // this sounds more jarring if it happens with no tolerance. if (value < 0.1f) { value = 0; } // We deliberately use SSA-like structure here to be able to see all the intermediate values in the debugger. // First, get the endpoint value of p float pValue = p[now.Time]; // Next, get the base value of p, in normalized terms ParameterDescription pDesc = p.Description; float pBaseValueNormalized = pDesc.Min == pDesc.Max ? pDesc.Base : (pDesc.Base - pDesc.Min) / (pDesc.Max - pDesc.Min); // Now we want to move from pBaseValueNormalized towards pValue, by an amount proportional to dragValue float newDestValue = pBaseValueNormalized + ((pValue - pBaseValueNormalized) * value); Parameter dest = m_parameters[p.Description]; if (m_baseParameters.Contains(p.Description)) { float baseValue = m_baseParameters[p.Description][now.Time]; float averagedDestValue = newDestValue; if (other != null && other.Contains(p.Description)) { averagedDestValue = (averagedDestValue + other[p.Description][now.Time]) / 2; } float adjustedDestValue = averagedDestValue; if (!p.Description.Absolute) { // only grow upwards from the base value, proportionately to how big the base value already is adjustedDestValue = baseValue + (averagedDestValue * (1 - baseValue)); } Spam.Model.WriteLine("parameter " + p.Description.Name + ": pValue " + pValue + ", pBVN " + pBaseValueNormalized + ", baseValue " + baseValue + ", adjustedDestValue " + adjustedDestValue); // clamp to [0, 1] because we may overshoot a bit with this algorithm dest[now.Time] = Math.Max(0, Math.Min(1f, adjustedDestValue)); } }
public override void GameUpdate(Moment now) { if (!m_dragStartLocation.HasValue) { HoloDebug.Assert(!m_currentKnobLocation.HasValue); // when not dragging, we handle all selection, etc. as usual; // e.g. we delegate to the usual player code m_parent.GameUpdate(now); m_parent.SceneGraph.Update(m_parent, m_parent.HolofunkModel.Kinect, now); } else { if (MicrophoneSelected) { // when the mike is being dragged, we don't have any touched loopies m_parent.TouchedLoopies.Clear(); } HoloDebug.Assert(m_currentKnobLocation.HasValue); Vector2 knobDelta = GetKnobDelta(m_parent.HandPosition); m_currentKnobLocation = m_dragStartLocation.Value + knobDelta; RecalculateDragEffect(now, knobDelta); m_parent.UpdateFromChildState(now); } m_sceneGraph.Update(m_parent, m_parent.HolofunkModel.Kinect, now); }
internal void Render(Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, GameTime gameTime, HolofunkView view, Color backgroundColor) { graphicsDevice.Clear(backgroundColor); m_model.SceneGraph.Render(now, graphicsDevice, spriteBatch, m_model.Content, view); }
internal void Update(PlayerHandModel playerHandModel, HolofunKinect kinect, Moment now) { // The position adjustment here is purely ad hoc -- the depth image still // doesn't line up well with the skeleton-to-depth-mapped hand positions. m_handGroup.LocalTransform = new Transform( kinect.GetJointViewportPosition( playerHandModel.PlayerModel.PlayerIndex, playerHandModel.IsRightHand ? JointType.HandRight : JointType.HandLeft) + MagicNumbers.ScreenHandAdjustment, new Vector2(MagicNumbers.LoopieScale)); // and make the mike signal update appropriately m_handMikeSignal.Update(now, false, playerHandModel.PlayerModel.PlayerColor); if (m_effectLabelShownMoment.HasValue) { Duration<Sample> elapsed = now.Time - m_effectLabelShownMoment.Value.Time; Color color = new Color(0, 0, 0, 0); if (elapsed > MagicNumbers.EffectLabelFadeDuration) { m_effectLabelShownMoment = Option<Moment>.None; } else { float fraction = 1f - ((float)(long)elapsed / MagicNumbers.EffectLabelFadeDuration); color = Alpha(fraction); } m_effectLabels[0].Color = color; m_effectLabels[1].Color = color; m_effectLabels[2].Color = color; m_effectLabels[3].Color = color; } // Debugging elbow arm pose label. ArmPose armPose = kinect.GetArmPose(m_parent.PlayerIndex, m_isRight ? Side.Right : Side.Left); m_armPoseLabel.Text.Clear(); m_armPoseLabel.Text.Append( armPose == ArmPose.AtChest ? "Chest" : armPose == ArmPose.AtMouth ? "Mouth" : armPose == ArmPose.OnHead ? "Head" : ""); m_armPoseLabel.LocalTransform = new Transform( kinect.GetJointViewportPosition(m_parent.PlayerIndex, m_isRight ? JointType.HandRight : JointType.HandLeft) + new Vector2(0, 50), new Vector2(0.7f)); }
public void Apply(ParameterMap parameters, Moment now) { foreach (HolofunkEffect effect in m_effects) { effect.Apply(parameters, now); } }
/// <summary> /// Start recording a new loopie; the result will be put into m_heldLoopie. /// </summary> /// <remarks> /// [KinectThread] /// </remarks> internal void StartRecording(Moment now) { lock (this) { // [KinectThread] to avoid torn writes to m_heldLoopie visible from game thread HoloDebug.Assert(!m_heldLoopie.HasValue); // Note that this may return null if we have no free streams and can't start recording. Loopie newLoopie = m_parent.StartRecording(now, new Transform(HandPosition), IsRightHand); m_heldLoopie = newLoopie ?? Option<Loopie>.None; } }
void CheckBeatEvent(Moment now, HolofunkMachine machine) { lock (machine) { Duration<Sample> sinceLastTransition = now.Time - machine.LastTransitionMoment.Time; if (sinceLastTransition > (long)HolofunkModel.Clock.ContinuousBeatDuration) { machine.OnNext(LoopieEvent.Beat, now); // TODO: suspicious rounding here... this is probably liable to lose fractional beats... // not clear how much beat events will wind up being used though. machine.LastTransitionMoment = machine.LastTransitionMoment.Clock.Time(machine.LastTransitionMoment.Time + (long)HolofunkModel.Clock.ContinuousBeatDuration); } } }
/// <summary> /// Start recording a new loopie; return null if we have no free streams. /// </summary> internal Loopie StartRecording(Moment now, Transform handPosition, bool isRight) { Loopie ret = m_parent.StartRecordingNewLoopie(now, m_playerIndex, isRight, AsioChannel, handPosition); return ret; }
/// <summary>Update the state as appropriate for "loopie mode" (the default, in which you are /// selecting and recording loopies).</summary> public override void GameUpdate(Moment now) { // Push the current microphone parameters to BASS. HolofunkModel.Bass.UpdateMicrophoneParameters(m_asioChannel, m_microphoneParameters, now); // We update the model of the state machine of each hand's model. // Each hand's state machine may have some layered model in place right now. lock (m_leftHandModel.StateMachine) { // [GameThread] ensure KinectThread doesn't concurrently mung the machine m_leftHandModel.StateMachine.GameUpdate(now); } lock (m_rightHandModel.StateMachine) { // [GameThread] ensure KinectThread doesn't concurrently mung the machine m_rightHandModel.StateMachine.GameUpdate(now); } PlayerSceneGraph.Update(this, m_parent.Kinect, now); }
internal void ShowEffectLabels(EffectSettings settings, Moment now) { m_effectLabels[0].Text.Clear(); m_effectLabels[0].Text.Append(settings.RightLabel); m_effectLabels[1].Text.Clear(); m_effectLabels[1].Text.Append(settings.UpLabel); m_effectLabels[2].Text.Clear(); m_effectLabels[2].Text.Append(settings.LeftLabel); m_effectLabels[3].Text.Clear(); m_effectLabels[3].Text.Append(settings.DownLabel); m_effectLabelShownMoment = now; }
protected override void DoRender(Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view, Transform parentTransform, int depth) { m_videoRateCounter += m_videoRateFunc(); if (m_videoRateCounter >= 1f) { m_videoRateCounter -= 1f; lock (this) { if (VideoStream != null) { s_totalRenders++; Slice<Frame, byte> videoImage = VideoStream.GetClosestSliver(now.Time + MagicNumbers.LatencyCompensationDuration); if (!videoImage.IsEmpty()) { if (videoImage.Equals(m_lastVideoFrame)) { // skip the setData s_redundantSetDatas++; } else { // blast the data in there with a single pointer-based memory copy videoImage.RawAccess((array, offset, count) => m_videoNode.Texture.SetData(array, (int)offset, (int)count)); m_lastVideoFrame = videoImage; } } } else { // ain't nothing to show m_videoNode.Texture.SetData(BlankTextureData); } } } base.DoRender(now, graphicsDevice, spriteBatch, content, view, parentTransform, depth); }
internal void UpdateFromChildState(Moment now) { foreach (Loopie loopie in TouchedLoopies) { // Loopies that are still being recorded can't be TouchedLoopies. // So it is safe to assume that loopie.Track is non-null here. loopie.Track.UpdateEffects(now); } }
/// <summary>Update the scene's background based on the current beat, and the positions of /// the two hands based on the latest data polled from Kinect.</summary> /// <remarks>We pass in the current value of "now" to ensure consistent /// timing between the PlayerState update and the scene graph udpate.</remarks> internal void Update( PlayerModel playerState, HolofunKinect kinect, Moment now) { m_headGroup.LocalTransform = new Transform( kinect.GetJointViewportPosition(PlayerIndex, JointType.Head) + MagicNumbers.ScreenHandAdjustment, new Vector2(1f)); m_headMikeSignal.Update(now, false, playerState.PlayerColor); m_leftHandSceneGraph.Update(playerState.LeftHandModel, kinect, now); m_rightHandSceneGraph.Update(playerState.RightHandModel, kinect, now); }
internal void Drag(Moment now, Vector2 userPosition) { float distanceSquared; float value = ScreenToValue(userPosition, out distanceSquared); Value = Math.Max(0, Math.Min(1, value)); m_parameter[now.Time] = Value; }
/// <summary> /// Update on [GameThread]. /// </summary> /// <param name="now"></param> public override void GameUpdate(Moment now) { InvalidateTouchedLoopies(); UpdateTouchedLoopies(HolofunkModel.Loopies, HandPosition, SceneGraph.HandDiameter * MagicNumbers.LoopieScale, PlayerModel.PlayerColor, HolofunkModel.Kinect.ViewportSize); List<Loopie> touched = TouchedLoopies; foreach (Loopie loopie in touched) { LoopieTouchEffect(loopie); loopie.Touched = true; } lock (this) { if (m_heldLoopie.HasValue) { m_heldLoopie.Value.Transform = new Transform(HandPosition); m_heldLoopie.Value.GameUpdate(now); } } }
protected override void DoRender( Moment now, GraphicsDevice graphicsDevice, ISpriteBatch spriteBatch, TextureContent content, HolofunkView view, Transform parentTransform, int depth) { if (m_totalBeats == 0) { // there is no actual track here; we do not render return; } Transform combinedTransform = parentTransform.CombineWith(LocalTransform); // How many measures? long measureCount = (m_totalBeats + 3) / 4; // note that the quarter-circle only takes up one quarter of quarterCircleRect; this is deliberate Rectangle quarterCircleRect = TextureRect(content.QuarterHollowCircle, combinedTransform.Scale * m_textureScale); Vector2 measuresOrigin = combinedTransform.Translation; measuresOrigin.X -= ((Math.Min(4, measureCount) * quarterCircleRect.Width) / 2); Color color = m_colorFunc(); Spam.Graphics.WriteLine(new string(' ', depth * 4) + Label + ": parentTransform " + parentTransform + ", localTransform " + LocalTransform + ", combinedTransform " + combinedTransform + ", color " + color.ToString()); for (int b = 0; b < m_totalBeats; b++) { float filledness; if (m_fillInEveryBeat) { if (b < m_currentBeat) { filledness = 1; } else if (b == m_currentBeat) { filledness = (float)m_fractionalBeat; } else { filledness = 0; } } else { if (b == m_currentBeat) { filledness = (float)(1 - m_fractionalBeat); } else { filledness = 0; } } DrawQuarterCircle(spriteBatch, content, quarterCircleRect, measuresOrigin, b, color, filledness, depth); } }
/// <summary>Stop recording at end of proper number of beats.</summary> /// <remarks> /// [KinectThread] /// </remarks> internal void StopRecordingAtCurrentBeat(Moment now) { lock (this) { // [KinectThread] to avoid torn writes to m_heldLoopie visible from game thread // May be no held loopie if we weren't able to start recording due to lack of free streams if (m_heldLoopie.HasValue) { lock (m_heldLoopie.Value) { // [KinectThread] to ensure atomic m_heldLoopie.StopRecordingAtNextBeat m_heldLoopie.Value.StopRecordingAtNextBeat(now, PlayerModel.MicrophoneParameters); m_heldLoopie = Option<Loopie>.None; } } } }
public override void GameUpdate(Moment now) { }
/// <summary>Update the scene's background based on the current beat, and the positions of /// the two hands based on the latest data polled from Kinect.</summary> /// <remarks>We pass in the current value of "now" to ensure consistent /// timing between the PlayerState update and the scene graph udpate.</remarks> internal void Update( HolofunkModel holofunkModel, HolofunKinect kinect, Moment now, float frameRateMsec) { // should do this once a second or so, to reduce garbage... if (++m_frameCount == MagicNumbers.StatusTextUpdateInterval) { m_frameCount = 0; m_statusText.Text.Clear(); long usedAudioMB = Audio.AudioAllocator.TotalReservedSpace / 1024 / 1024; long freeAudioMB = Audio.AudioAllocator.TotalFreeListSpace / 1024 / 1024; long usedVideoMB = holofunkModel.VideoAllocator.TotalReservedSpace / 1024 / 1024; long freeVideoMB = holofunkModel.VideoAllocator.TotalFreeListSpace / 1024 / 1024; m_statusText.Text.AppendFormat( "Time: {10}:{11:D2} | BPM: {0} | Update FPS: {1} | Kinect FPS: {2} | CPU: {3}%\nAudio: {4}/{5}MB | Video: {6}/{7}MB | Free streams: {8}\n{9}\n", Clock.BPM, frameRateMsec == 0 ? 0 : Math.Floor((1000f / frameRateMsec) * 10) / 10, kinect.m_totalFrames / Clock.Now.Seconds, Math.Floor(Audio.CpuUsage * 10) / 10, usedAudioMB - freeAudioMB, usedAudioMB, usedVideoMB - freeVideoMB, usedVideoMB, Audio.StreamPoolFreeCount, (Spam.TopLine1 == null ? "" : Spam.TopLine1) + "\n" + (Spam.TopLine2 == null ? "" : Spam.TopLine2), DateTime.Now.Hour, DateTime.Now.Minute); } // Scale to byte and use for all RGBA components (premultiplied alpha, don't you know) Color backgroundColor = FloatScaleToRGBAColor(1 - (now.FractionalBeat / 1.2f)); m_background.Color = backgroundColor; m_background.SecondaryColor = backgroundColor; m_beatNode.Update(now); Texture2D currentSlide = Content.Slides[holofunkModel.SlideIndex]; m_slide.Texture = currentSlide; m_slide.LocalTransform = new Transform(new Vector2( m_canvasSize.X - (int)(currentSlide.Width), currentSlide.Height / 8)); m_slide.Color = holofunkModel.SlideVisible ? Color.White : new Color(0, 0, 0, 0); Spam.Graphics.WriteLine("EndUpdate"); }
/// <summary> /// Update the model at the current moment. /// </summary> /// <remarks> /// [GameThread] /// </remarks> public abstract void GameUpdate(Moment now);
internal void Update(Moment now) { float interpolatedBaseValue = (m_parameter.Description.Base - m_parameter.Description.Min) / (m_parameter.Description.Max - m_parameter.Description.Min); float value = Value; if (Math.Abs(value - interpolatedBaseValue) < 0.02f) { // set some minimum value so default values are still visible on the slider value = interpolatedBaseValue + 0.02f; } m_sliderLine.SetEndpoints(ValueToLocal(interpolatedBaseValue), ValueToLocal(value)); }
internal void Update( PlayerModel playerState, HolofunKinect kinect, Moment now) { }