Advertisement

WPF - Presenting 2D sprites (2D map editor)

Started by November 23, 2015 06:58 PM
11 comments, last by Eiron 9 years ago

Thanks for checking in on me!

24234dd616.png

Made quite some progress in the meantime, however, I just hit another speed bump and have been spending most of my day on it.

As visible in the screenshot, I manage to draw on the canvas with my mouse but either only through single clicks (tedious) or with a MouseEnter event (drawing always on..)

Neither are what I wished for and I tried to work with a MouseDown event, which doesn't work. After some research I figured PreviewMouseDown should do the trick where MouseDown doesn't, but this doesn't work as well.

How can I make 'click dragging' work to paint with tiles?

This is my xaml part:


<DataTemplate>
                            <Image Source="{Binding MapTileImage}" Stretch="Fill" Width="{Binding Width}" Height="{Binding Height}">
                                <Image.InputBindings>
                                    <MouseBinding MouseAction="LeftClick" Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ChangeTilesCommand}" CommandParameter="{Binding .}"/>
                                </Image.InputBindings>

                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="MouseEnter">
                                        <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ChangeTilesCommand}" CommandParameter="{Binding .}" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </Image>
                        </DataTemplate>

And in MainViewModel


private RelayCommand<BitmapModel> _changeTileCommand;
public RelayCommand<BitmapModel> ChangeTilesCommand {
    get { return _changeTileCommand ?? (_changeTileCommand = new RelayCommand<BitmapModel>(UpdateTile)); }
}

with


void UpdateTile(BitmapModel tile) {           
            if (tile == null) return;
            if (SelectedMapTile == null) return;

            tile.MapTileImage = SelectedMapTile.MapTileImage;
}

Of course, the MouseAction is redundant with the introduction of Event "MouseEnter", but MouseEnter works regardless of the button state, which is my problem. No other event seems to work from MSDN. What can I do?

I am not quite sure what do you mean by MouseDown event not working? Have you tried to hook the event directly to some method in view's code-behind? Is it possible that there is something wrong with your binding expressions? You can diagnose such errors by enabling first-chance exceptions in the debugger, or simply by observing the output window while debugging your application. If you see some binding errors in the output, then this might be the culprit.

Another thing that comes to my mind, if your images are initially empty, they might simply be invisible for hit tests. If you initialize the images with some default content, even containing just transparent pixels, that would make them visible for hit tests, causing mouse events to be received as expected.

Regarding the "always drawing" problem, both MouseDown and MouseEnter events pass MouseEventArgs, which can be used to check the button state. I am not certain if it is possible to do that directly in XAML, but you can always hook the events to some methods in the view's code-behind, check the mouse button state manually, and invoke the view-model's command when necessary. Of course, nothing stops you from implementing some kind of a "conditional" event trigger yourself, that only fires when a certain mouse button is pressed, but I think that would be an overkill in your particular case.

Advertisement

Allright!!

This:


<ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Image Source="{Binding MapTileImage}" Stretch="Fill" Width="{Binding Width}" Height="{Binding Height}">                               

                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="MouseEnter">
                                        <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ChangeTilesCommand}" CommandParameter="{Binding .}" />
                                    </i:EventTrigger>
                                    <i:EventTrigger EventName="MouseLeftButtonDown">
                                        <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.DrawingCommand}" PassEventArgsToCommand="True"/>
                                        <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.ChangeTilesCommand}" CommandParameter="{Binding .}"/>
                                    </i:EventTrigger>
                                    <i:EventTrigger EventName="MouseLeftButtonUp">
                                        <command:EventToCommand Command="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.DrawingCommand}" PassEventArgsToCommand="True"/>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </Image>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>

in combination with:



private RelayCommand<BitmapModel> _changeTileCommand;
        public RelayCommand<BitmapModel> ChangeTilesCommand {
            get { return _changeTileCommand ?? (_changeTileCommand = new RelayCommand<BitmapModel>(UpdateTile, CanDraw)); }
        }

private RelayCommand<MouseEventArgs> _drawingCommand;
public RelayCommand<MouseEventArgs> DrawingCommand {
            get { return _drawingCommand ?? (_drawingCommand = new RelayCommand<MouseEventArgs>(MouseDown)); }
}


void MouseDown(MouseEventArgs mouse) {
            if (mouse.LeftButton == MouseButtonState.Pressed) _mouseDown = true;
            else if (mouse.LeftButton == MouseButtonState.Released) _mouseDown = false;
}

bool CanDraw(BitmapModel tile) {
            return _mouseDown;
}

Made it work! Thanks for your input!

Additional info: "MouseDown" and other events didn't work because of my Image.InputBinding I figured, had to get rid of it. Working with MouseEventArgs did the trick.

This topic is closed to new replies.

Advertisement