Silverlight 2 Beta 1 - HitTest is buggy with ScaleTransform
Last post 05-13-2008 8:01 AM by Kbalz. 2 replies.
Sort Posts:
05-07-2008 4:10 AM
Silverlight 2 Beta 1 - HitTest is buggy with ScaleTransform

I'm trying to use fairly simple hit testing for collision detection between two objects.  I started with Andy's example (http://www.andybeaulieu.com/Default.aspx?tabid=67&EntryID=95).  I downloaded the code and it worked.  Pixel-accurate hit testing.  Then I put a ScaleTransform on the main canvas in Page.xaml, like this:

<Canvas.RenderTransform>

     <ScaleTransform ScaleX="2" ScaleY="2" />

</Canvas.RenderTransform>

After putting a scale transform on the main canvas, hit testing for the child UserControls stopped working.  Specifically, the rect.Intersect worked, but the Hit Testing (testing for points) did not return any results.  If I scaled it down (setting the ScaleX and ScaleY to .5), then the hit testing worked. 

I got curious and tried putting the ScaleTransform on the AsteroidBig UserControl.  When I did this, the hit testing only worked for the original size of the object, not the new size of the object. 

I also tried putting a RotateTransform on the AsteroidBig UserControl.  Hit testing seemed to work pretty well in this condition. 

Is this a bug in SL2 Beta1, or am I doing something wrong? 

Does anyone know a more reliable method for pixel-accurate collision detection in SL2 Beta1?

Steve Nyholm "snyhol"
blog: http://www.AListForEverything.com

snyhol

Joined on 05-07-2008
California
Posts 6
05-09-2008 2:24 AM
Marked as Answer
Re: Silverlight 2 Beta 1 - HitTest is buggy with ScaleTransform

Hello, the problem is: Canvas.Left/Top property don't change along with scaling. So the UserControlBounds returns a wrong Rect. UserControlBounds should take into account the scaling factor. Try something like this:

public Rect UserControlBounds(FrameworkElement control)

{

Point ptTopLeft = new Point(Convert.ToDouble(control.GetValue(Canvas.LeftProperty)) * ((ScaleTransform)cnvHitTest.RenderTransform).ScaleX,

Convert.ToDouble(control.GetValue(Canvas.TopProperty)) * ((ScaleTransform)cnvHitTest.RenderTransform).ScaleY);

Point ptBottomRight = new Point((Convert.ToDouble(control.GetValue(Canvas.LeftProperty)) + control.Width) * ((ScaleTransform)cnvHitTest.RenderTransform).ScaleX,

(Convert.ToDouble(control.GetValue(Canvas.TopProperty)) + control.Height) * ((ScaleTransform)cnvHitTest.RenderTransform).ScaleY);

return new Rect(ptTopLeft, ptBottomRight);

}

 

shanaolanxing - Please mark the posts as answers if they help and unmark if they don't.

Yi-Lun Luo - MSFT

Joined on 10-29-2007
Posts 1,084
05-13-2008 8:01 AM
Re: Silverlight 2 Beta 1 - HitTest is buggy with ScaleTransform

I don't mean to hijack - but what about outside of that application? I just dropped a path on a canvas, scaled the canvas and no longer can hittest the path.

Xaml:

<UserControl x:Class="HitTest.Page"

xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

MinWidth="400" MinHeight="300">

<Grid x:Name="LayoutRoot" Background="White">

<Grid.RowDefinitions>

<RowDefinition Height="*"></RowDefinition>

<RowDefinition Height="40"></RowDefinition>

</Grid.RowDefinitions>

 

<Canvas x:Name="C1" Background="Red" Grid.Row="0">

<Canvas.RenderTransform>

<ScaleTransform x:Name="ZoomTransform"></ScaleTransform>

</Canvas.RenderTransform>

<Path Name="Path1" Fill="Transparent"  Stroke="Black" StrokeThickness="3" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Canvas.Left="8.214" Canvas.Top="42.069">

<Path.RenderTransform>

<RotateTransform Angle="180" CenterX="24" CenterY="33"></RotateTransform>

</Path.RenderTransform>

<Path.Data>

<PathGeometry>

<PathFigure StartPoint="24, 66" IsFilled="True">

<LineSegment Point="0, 30"></LineSegment>

<ArcSegment Point="0,24" Size="3.462,3.462" IsLargeArc="True" SweepDirection="Counterclockwise"></ArcSegment>

<ArcSegment Point="48, 24" Size="24,24" SweepDirection="Clockwise" IsLargeArc="True"></ArcSegment>

<ArcSegment Point="48,30" Size="3.447,3.447" IsLargeArc="True" SweepDirection="Counterclockwise"></ArcSegment>

<LineSegment Point="24, 66"></LineSegment>

</PathFigure>

</PathGeometry>

</Path.Data>

</Path>

</Canvas>

<TextBlock x:Name="C1Text" Grid.Row="1"></TextBlock>

</Grid>

</UserControl>

 

Code:

public partial class Page : UserControl

{

public Page()

{

InitializeComponent();

C1.MouseMove +=
new MouseEventHandler(C1_MouseMove);

ZoomTransform.ScaleX += 2;

ZoomTransform.ScaleY += 2;

}

void C1_MouseMove(object sender, MouseEventArgs e)

{

Point p = e.GetPosition(C1);

C1Text.Text = "";

foreach (UIElement e1 in HitTest(p))

{

C1Text.Text += " " + e1.GetType().Name;

}

}

}

 

Kbalz

Joined on 04-21-2008
Posts 25