28 Sep 2011

The Concept Lab: Stories From The Front

Last Wednesday I was invited by one of our partners, Fluxx, to talk at an evening event they hosted; The DNA of Innovation.  They wanted me to share my war stories from working in Concept Labs and Rapid Prototyping, something we have years of experience with here at Red Badger.

The Concept Lab has become an ever popular way of exploring and proofing big ideas and new concepts, but making it work and getting it right is far from easy.  Having worked on a whole stack of challenging Labs over the last 4 years, Head of Experience Design at Fluxx, Paul Dawson, asked me to share some of those experiences with luminaries invited from 15 of the worlds most notable brands.

DistillQuote

The key theme of a lab is that of discovery – for good or bad.  You take a multi-disciplined crack team, set them some large goals (and lots of them), give them the best tools, the best tech, remove all impediments and then lock them away in a collaborative space for 3 - 6 weeks and let them prove, or disprove, the objectives of the lab.

The idea is not so much to do things differently than you normally would, crazily churning out awful code, but to distil the best industry process down into your 3 – 6 week period, using the bare essentials of each process; taking away as much as you can, but stopping just before your yield drops.

With that thesis in mind I decided to apply the same methodology to my talk and take three Labs I’d worked on and, in just 10mins, whip through what each set out to achieve, what we did and what we discovered.  As we toured through Labs for Tesco, Haynes and Microsoft – looking at concept artwork and videos of working product it was great to see the audience immediately “getting it”.

That’s what Labs are so great at doing – bringing lots of tough ideas to life, quickly.

“Pocket Mechanic” (a Lab we conducted for Haynes) is a case in point, the actual rapid prototype below was put together in less than a week, but every time we put it into someone's hands to play with - they love it. They instantly see the value in the concept. That’s pretty powerful stuff.

If you can put a device, with working software, in the hands of a decision maker and show them something within 4 weeks, it makes their decision a lot easier than if you simply tell them you can do something.  What’s more, the subsequent decision about what to spend the real money on is going to be a much wiser and confident one if much of the discovery work has already been done.

FailureIsAnOptionQuote

In a Lab, failure is an option; you set out with lots of tough goals, safe in the knowledge that you expect some of them not to work.  The value in making your mistakes early, in a controlled environment, as opposed to the production development cycle cannot be underestimated.

It’s important to remember that Labs work best when the goals are many and tough – for the team it should feel like a challenge, it should be intensively productive and if you really have the crack team you need, they’ll revel in it.

07 Feb 2011

Birdsong Feedback Is Moving

One of the changes we’re making with the upcoming release of v1.1 of Birdsong is how we deal with support and feedback.  As of today we have moved support, feedback, user forums and feature requests all under one happy roof at our brand new support portal at http://support.red-badger.com

Naturally you’ve got questions as to why we’re moving everything and what’s going to happen to the feedback you’ve already provided; hopefully we can answer those questions here.

Why the change?
We want to offer the best support, respond to all feedback and hear your feature requests.  We couldn’t do that all in one place under our old feedback site.  With the new one we can.

What happens to requests I’ve already made?
Worry not, if you head over to the new Feature Requests forum you’ll find them all there.  We’ve moved over all the feedback, all the comments and kept a record of the number of votes each request had.

How do I vote for something on the new site?
The new forum has a similar voting concept that will allow the most popular features to bubble to the top.  Instead of assigning a limited number of votes, you can simply choose to “like” an idea.

What happened to my votes?
Unfortunately we can’t alter the number of votes an idea has on the new site, so it will appear everything has started back at 0.  Fear not however, we’ve recorded the number of votes each idea had in the description on the new site and we promise we’ll take them into account when prioritising features.

What else do I get?
Announcements on upcoming releases, a Community Help forum so the Birdsong community can start helping each other out, and an integrated experience with our new support ticketing system.

 

We’d like to thank everyone who’s provided feedback and feature requests to date – your feedback genuinely has an impact on what we choose to work on next – so don’t stop!

The new home of support and feedback for Birdsong is http://support.red-badger.com

28 Jan 2011

Birdsong Quick Tip: Tweet Property Icons

One of our favourite features of Birdsong is the Tweet Property Icons – they appear to the bottom right of tweets in your timeline and quickly let you know what lies within.  Here’s a quick run-down of what they look like and what they mean.

ConversationConversation

If you see the conversation icon, it indicates that the tweet was “in reply to” someone and you’ll be able to tap through to the conversation and see every response in context.

 

 

 

PicturePicture

Birdsong’s integrated picture viewer recognises and integrates with all the major picture services (twitpic, yfrog, flickr, plixi and moby).  If you see the picture icon, you’ll get a thumbnail of the picture which you can tap on to view in full screen.

 

PlacePlace

We integrate with Bing Maps, so if your friends geo-tag their tweets you’ll get a thumbnail map of their location and be able to tap through to a full interactive Bing Map.

 

 

FavoriteFavourite

If you’ve earmarked a tweet as a favourite, you’ll see the star tweet property icon in your timeline.

 

 

 

ProtectedProtected

Some of your friends may choose to limit who can see their tweets and protect their account – if you’re one of the special ones,  you can feel even more special with this delightful padlock icon.

 

Follow us at @redbadgerteam to pick up on more quick tips!

Download Birdsong from Zune Now!

26 Jan 2011

Birdsong Quick Tip: Quickly jump to the top of a list

Follow us at @redbadgerteam to pick up on more quick tips!

22 Jan 2011

Windows Phone 7 Analytics with Mixpanel

Having tried out the Microsoft’s WP7 analytics partner solution, PreEmptive, I was left underwhelmed by the tooling, UI and speed of reporting.  I like Google Analytics, but getting that working looked like a fair bit of inventive hackery and involves referencing the Silverlight Analytics Framework and who needs “yet another dll”™ in their app?  I’d also heard a few reports that the Google Analytics approach was pretty slow.  So inspired by Nick Gravelyn I thought I’d give Mixpanel a shot.

The beauty of the Mixpanel’s RESTful API is in its simplicity – there’s one method and practically everything you need to know about it is contained on this one page.  Each call logs an event and each event can have a collection of properties.  For example we log a “launch” event when our application starts up with the following properties: istrial, version, locale.  You don’t have to predefine any events or properties – just send them.

When you send an event, there are 2 properties you’re always going to need: token and distinct_id.  Token is the token Mixpanel generates for you when you create a project on their site and distinct_id is an arbitrary string you provide to define what makes a user unique.  On Windows Phone it makes sense to use the DeviceUniqueId from DeviceExtendedProperties.  This is returned as a byte array, so you’ll need to Base64 encode it to use as the distinct_id.

Finally Mixpanel wants your event object serialized into JSON (for which we can use Json.Net) and then Base64 encoded into a string.

Our TrackingEvent class inherits from Dictionary<string, object> to embody the name-value-pair nature of an event’s properties and encapsulates all of the serializing and encoding behaviour into a GetData method.  It looks a little something like this:

public class TrackingEvent : Dictionary<string, object>
{
    private const string DistinctIdProperty = "distinct_id";

    // TODO: Your Mixpanel token goes here
    private const string MixpanelToken = "";

    private const string TokenProperty = "token";

    private readonly string eventName;

    public TrackingEvent(string eventName)
    {
        this.eventName = eventName;
    }

    public string GetData()
    {
        if (!this.ContainsKey(TokenProperty))
        {
            this.Add(TokenProperty, MixpanelToken);
        }

        if (!this.ContainsKey(DistinctIdProperty))
        {
            this.Add(DistinctIdProperty, GetDeviceUniqueId());
        }

        JProperty[] properties =
            this.Select(keyValuePair => new JProperty(keyValuePair.Key, keyValuePair.Value.ToString())).ToArray();

        var json = new JObject(
            new JProperty("event", this.eventName), new JProperty("properties", new JObject(properties)));

        return Convert.ToBase64String(Encoding.UTF8.GetBytes(json.ToString()));
    }

    private static string GetDeviceUniqueId()
    {
        object deviceUniqueId;
        return DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out deviceUniqueId)
                   ? Convert.ToBase64String((byte[])deviceUniqueId)
                   : "anon";
    }
}

Next we need to actually send the HTTP request – for this we use the always excellent Reactive Extensions (Rx) which means we can easily make the call asynchronously using the thread pool and process the response in a terse and elegant manner.

For the purpose of this example, we’ll demonstrate this via a static Track() method and then explain what’s happening:

public static class Analytics
{
    public static void Track(TrackingEvent trackingEvent)
    {
        var uriBuilder = new UriBuilder("http://api.mixpanel.com/track")
            {
               Query = string.Format(CultureInfo.InvariantCulture, "data={0}", trackingEvent.GetData()) 
            };

        WebRequest webRequest = WebRequest.Create(uriBuilder.Uri);

        Observable.FromAsyncPattern<WebResponse>
            (webRequest.BeginGetResponse, webRequest.EndGetResponse)()
                .SubscribeOn(Scheduler.ThreadPool)
                .Select(GetResponse)
                .Subscribe(
                    response => Debug.WriteLine("Response: {0}", response), 
                    exception => Debug.WriteLine("Error: {0}", exception.Message));
    }

    private static string GetResponse(WebResponse webResponse)
    {
        if (webResponse.ContentLength > 0)
        {
            using (var streamReader = new StreamReader(webResponse.GetResponseStream()))
            {
                return streamReader.ReadToEnd();
            }
        }

        return string.Empty;
    }
}

If  you’re not familiar with Rx the FromAsyncPattern call might look a bit daunting, but it’s incredibly elegant.  It wraps the asynchronous Begin/End pattern and produces an IObservable which you can subscribe to.  Because it’s an IObservable we can instruct Rx to execute the subscription on the thread pool.  Next we use a Select to project the WebResponse returned into a string via the GetResponse() method and then subscribe to the result.

Mixpanel simply returns a 1 or a 0 to tell you whether your request was logged, so day-to-day you don’t really care about the response, but during development it’s handy to see what’s coming back.  It’s worth noting that in my discussions with Mixpanel the 1 or 0 is really just an indication of whether they managed to deserialize your JSON (at time of writing), so it’s possible you could get a 1 back but still not get data logged because you forgot to set your token property.  Luckily Mixpanel stats are “real time” – so it’s easy to check that you’re data’s getting through.

Finally we just make a call to our Track method in our codebase whenever we want to track an event:

Analytics.Track(
    new TrackingEvent("launch")
        {
            { "istrial", new LicenseInformation().IsTrial() },
            { "locale", Thread.CurrentThread.CurrentUICulture.Name },
        });

Be aware that some values you might want to track, such as IsTrial, have overhead to obtain and should ideally be done once per session and stored, but you get the idea.  It’s probably also worth thinking about disabling tracking when you’re in debug/developing to save wasting data points or skewing your production figures.

It’s early days with Mixpanel, but so far we’re liking what we see.  If you’re planning to try Mixpanel and found this useful then feel free to signup via this referral link and we’ll both get an extra 5,000 data points and this delightful carriage clock… http://mixpanel.com/user/register/700134331/ (clock not included).

23 Oct 2010

XPF: Data Binding 101 (Part 1) - What, Why, How?

Data Binding is one of XPF’s features that we’re excited about – bringing data binding to the world of XNA helps to encourage building of loosely coupled applications and helps enable the separation of presentation from implementation logic.  We’ve previously discussed the inner workings of data binding in our insider post but for those whom data binding maybe an abstract concept, this series of posts is designed to introduce you to both the concepts and the implementation.  Let’s walk through what it is, why you should use it and what XPF offers.

What is Data Binding?

Data binding can essentially be thought of as an implementation of the Observer Pattern, where the UI is the observer and the domain model the subject.

“The observer pattern (a subset of the publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.”
- Wikipedia

In reality XPF turns that concept on its head in that the UI elements maintain the list of subjects and hooks onto them to watch for updates, it also supports two-way conversations between subjects and observers but we’ll come onto that later.

Let’s step back slightly; XPF goes a bit further than the observer pattern so let’s change our language terms to something more fitting.  Instead of “subject” we’ll use source and in-lieu of “observer” let’s say target.  Let’s look at what that means in practical terms:

image

In this example we have a player class that exposes the player’s score via a property.  We also have a user interface which is going to display the player’s score as it updates.  In this example the score property on the player object is the source of our data and the text block in the UI is the target.  In a situation like this we would use data binding to establish a relationship between our player class and our UI once and then never worry about it again, knowing that if we alter the player’s score in our domain model the UI will automatically get updated via data binding.

Why use Data Binding?

Data binding is an enabler of other patterns and practices that ultimately make your life easier and your code easier to manage.

The quest to isolate domain logic from the user interface has spawned dozens of architectural patterns, MVC and MVVM being amongst the most popular at the moment.  Both concentrate on allowing your domain model to be focused on its job whilst being agnostic to any UI that maybe influenced by it.  This has some distinct advantages.

Generally speaking the logic you use to determine whether a player’s score should increase and the logic you use to display that change in score are very different beasts, as such when tackled together they don’t tend to produce particularly focused units of code.

Producing focused, isolated units of code makes your codebase easier to understand and eases unit testing.  If your player class doesn’t care about UI, then it doesn’t need to know anything about any graphics related dependencies, thus a dependency is dropped, unit testing is eased, and your code base is simpler and less brittle as a result.

Data binding encourages this separation by providing a bridge between the two disciplines.

Data Binding in XPF

As mentioned previously, XPF turns the Observer pattern on its head slightly in regards to which side of the equation maintains the list of observers (targets) that should be updated when the subject (source) changes.

In XPF the target maintains the list of sources with which it is bound.  The switch in responsibility here frees up the source (domain model) from being anything much other than a POCO.

The target is a UI element; all elements in XPF inherit from ReactiveObject and expose Reactive Properties which can be bound to.  Together ReactiveObject and ReactiveProperty provide the required mechanisms for data binding to work.

Three modes of binding are supported: one way, one way to source and two way.  The modes describe the direction in which data flows relative to the target.  One way is from the source to the target, one way to source is from the target to the source and two way moves data in both directions.imageWhilst all of the heavy lifting is taken care of by ReactiveObject and ReactiveProperty the source (domain model) side of the equation still has to agree to a couple of rules if it wants to take part.  The source needs to expose a known hook for the binding system to latch onto which it can use as a channel to push data in one or both directions.

In XPF this hook is provided by the new IObservable<T> and IObserver<T> interfaces introduced in .Net 4.0 (and on WP7) which align to the concept of moving data in either direction.  They are the mathematical dual of IEnumerable<T> and IEnumerator<T>, in that they push rather than pull their data.

“The IObserver<T> and IObservable<T> interfaces provide a generalized mechanism for push-based notification, also known as the observer design pattern. The IObservable<T> interface represents the class that sends notifications (the provider); the IObserver<T> interface represents the class that receives them (the observer).”
- MSDN

One way binding expects an IObservable<T> as its source which the binding system subscribes to.  One way to source expects an IObserver<T> to which the binding system can push updates.  Two way expects both.

How to use Data Binding

Continuing on the example application above, the score would be defined in the UI as a TextBlock and we would bind our player class to its text property.

Bindings are always setup against a ReactiveProperty on a ReactiveObject via the Bind() method.  In XPF all controls ultimately inherit from ReactiveObject and most expose a number of ReactiveProperty properties that can be bound to.

Each control exposes the Reactive Properties available for binding as static members, here are some of the Reactive Properties exposed by TextBlock, all of which can be bound to:

TextBlockReactiveProperties

Once we have an instance of a TextBlock we can call its Bind method and specify what property we want to bind to along with the mode and source we want to use.  It’s at this point we decide what binding mode we want to use by providing either an IObservable<T> (one way), IObserver<T> (one way to source) or both (two way):

TextBlockBind

The binding is now set and in the example above any changes to the source provided would update the TextBlock’s text property, meaning we don’t have to worry about updating the UI ourselves.

Don’t worry if all this talk of observables and observers is worrying you, we’ll cover the BindingFactory in a future post that can be used to create bindings around normal typed properties, but it's good to get an understanding from the ground up.

Next Time…

In the next post in this series we’ll look at a domain object that exposes IObservable<T> and IObserver<T> properties and build a working sample that uses them to create both one way and two way bindings.

18 Oct 2010

XPF Video: Windows Phone 7 User Group Presentation

At the last Windows Phone User Group, we took to the stage of Imperial College London and gave an introductory presentation on XPF.  For those that weren’t able to make it, we’re pleased to be able to present it to you now in 720p via the magic of IIS Smooth Streaming (we’ll also be making a downloadable version available shortly).

Topics include:

  • Why we need XPF
    • 2D in XNA Today
  • What is XPF
    • Controls
    • Extensibility
  • How to use XPF
    • Live demo: Embedding XPF inside a 3D application on WP7.

We’ve updated the XPF Samples package to include the full source code for the final 3D Basketball Game we built - you can download it here.

Massive thanks go to our good friend Mr Hornsby, the man behind the filming and editing of this presentation and of course Matt Lacey for organising the WPUG.  If you’d like to have a chat about video coverage of your event, drop Steve an email: steve@stephenhornsby.com

12 Oct 2010

XPF Control Tour: ItemsControl

Updated 2010-10-20: Altered BindingFactory.CreateOneWay<SolidColorBrush> to CreateOneWay<Brush> - co/contravariance isn’t supported on WP7.  ItemTemplate now passes DataContext as an argument of the Func (Build 37+).

As XPF matures the number of controls available increases, but it’s largely down to the early adopter to seek them out and figure out how to use them.  Our thinking here is that most developers will have had some WPF/Silverlight experience so the usage pattern will be easy to work out.  That may have been a little presumptuous on our part, so in a series of short and sharp posts we’ll take a tour through some of the less obvious controls.

First up the ItemsControl, one of my favourites.  In XPF if you want to repeat a block of UI for n number of items, you invariably want an ItemsControl.  Think ListBox, ComboBox or maybe items in a menu.

Let’s look at a complete example and it’s output:

public class MyComponent : DrawableGameComponent
{
    private RootElement rootElement;

    public MyComponent(Game game)
        : base(game)
    {
    }

    public override void Draw(GameTime gameTime)
    {
        this.rootElement.Draw();
        base.Draw(gameTime);
    }

    public override void Update(GameTime gameTime)
    {
        this.rootElement.Update();
        base.Update(gameTime);
    }

    protected override void LoadContent()
    {
        var spriteBatchAdapter = new SpriteBatchAdapter(new SpriteBatch(this.GraphicsDevice));
        var primitivesService = new PrimitivesService(this.GraphicsDevice);
        var renderer = new Renderer(spriteBatchAdapter, primitivesService);

        this.rootElement = new RootElement(this.GraphicsDevice.Viewport.ToRect(), renderer);

        var colors = new List<SolidColorBrush>
            {
                new SolidColorBrush(Colors.Red), 
                new SolidColorBrush(Colors.Blue), 
                new SolidColorBrush(Colors.Yellow)
            };

        var itemsControl = new ItemsControl
            {
                ItemsSource = colors, 
                ItemTemplate = dataContext =>
                    new Border
                        {
                            Width = 50, 
                            Height = 50, 
                            Margin = new Thickness(10), 
                            Background = new SolidColorBrush(Colors.Gray)
                        }
            };

        this.rootElement.Content = itemsControl;
    }
}

image

That’s all standard XPF scaffolding code right up until we define a list of colors and define an ItemsControl.  Things to note:  ItemsSource is set to the list of colors (you can use anything that implements IEnumerable).  The ItemTemplate property is a Func<IElement> (all controls in XPF implement IElement) and is executed for each item specified in ItemsSource, hence we defined 3 colors in our list and we got 3 borders rendered.

The DataContext & Data Binding

At the moment each Border background is gray.  How do we get it to use the colors in our list?  Each item that the ItemsControl generates will have it’s DataContext property set to it’s associated item in the ItemsSource.  Using XFP’s data binding, we can bind to that DataContext property in our ItemTemplate and dynamically assign the background color of each Border:

var itemsControl = new ItemsControl
{
    ItemsSource = colors,
    ItemTemplate = dataContext =>
    {
        var border = new Border
        {
            Width = 50,
            Height = 50,
            Margin = new Thickness(10)
        };

        border.Bind(
            Border.BackgroundProperty,
            BindingFactory.CreateOneWay<Brush>());

        return border;
    }
};

image

Whilst the data context of each item is automatically set by XPF to support various binding scenarios, you’ll also note that the data context is passed as an argument of the ItemTemplate function.  This facilitates run-time decisions about the template that should be returned.

If you’re interested in all the Data Binding options, be sure to check out our Inside XPF: Data Binding post.

ItemsPanel

The way in which the ItemsControl lays out it’s children can be configured via it’s ItemsPanel property.  By default the ItemsControl will use a StackPanel (which itself defaults to an orientation of vertical).  But you can change the ItemsControl to use anything that inherits from Panel, meaning you can apply your own layout logic.  Custom panels is a subject in-upon itself which we’ll cover in a future post, but the process is almost identical to creating a custom panel in WPF/Silverlight, so generally speaking any WPF/Silverlight panel implementation you can find, will work in XPF.

For now, let’s change our ItemsPanel to a horizontal StackPanel:

var itemsControl = new ItemsControl
{
    ItemsPanel = new StackPanel { Orientation = Orientation.Horizontal },
    ItemsSource = colors,
    ItemTemplate = dataContext =>
    {
        var border = new Border
        {
            Width = 50,
            Height = 50,
            Margin = new Thickness(10)
        };

        border.Bind(
            Border.BackgroundProperty,
            BindingFactory.CreateOneWay<Brush>());

        return border;
    }
};

image

 

Observable Collections

In our example so far we’ve been binding our ItemsSource to a List<T> which means after creation our ItemsControl is pretty much not going to change.  If however you set the ItemsSource to a collection that implements INotifyCollectionChanged (such as the commonly used ObservableCollection<T>) the ItemsControl will automatically hook onto CollectionChanged event and dynamically, update it’s children.  All actions are supported meaning you can add, remove, replace or move items in the bound collection and the ItemsControl will automatically update it’s layout to reflect the changes.

Using the ItemsControl with an observable collection and data binding is another great example of XPF helping you separate your presentation and implementation concerns.

29 Sep 2010

Talking XNA with Shawn Hargreaves and Charles Cox

To a lot of .Net developers XNA often appears to be a bit of an enigma - they might know roughly what it is, but they’re not really sure of its placement in the market or relevance to their work.  With Windows Phone 7 XNA is being edged into the limelight a little more and developers will no doubt be wondering whether it’s for them.

One of the great things about the work we’re doing with XPF, is in lowering that bar to entry.  XPF’s out-of-the-box controls will be familiar to you if you’ve come from a WPF/Silverlight background, but they still embrace the mechanics of XNA; leading you slowly into the wonderful world of 3D programming.

In a recent Channel 9 video Shawn Hargreaves and Charles Cox, from the XNA team, give a great interview on what XNA is, how it’s used, and the platforms it’s available on.  If you’re at all interested in XNA, but aren’t sure where to start – this is a great intro.

One of the subjects that comes up is the oft-asked “XNA and XAML” question and you might notice that at around the 32min mark Shawn happens to mention something that sounds a lot like XPF. ;)

So if you’re interested in dipping your toe in the XNA water, why not start by checking out our XPF Getting Started guide, download the sample code and let us know how you get on.

Tags , ,
26 Sep 2010

XPF: Introducing Adapters (and Clipping)

Chocolate Tools by Janne Moren One of the things we’ve always been very careful to do with XPF is to make sure that it doesn’t really know anything about XNA.  Everything is interface driven and the link to XNA is only made at the “last minute” in the implementation of those interfaces.

This gives us the advantage of easing our BDD specs (everything can be mocked) but it also opens up another intriguing possibility - XPF doesn’t necessarily have to be used for XNA.

To reinforce this separation we’ve introduced the concept of adapters.  Those currently using XPF will know that we already have adapters, in the pattern sense of the word, for SpriteBatch, SpriteFont and Texture2D – but we’re extending the adapter concept to encompass everything required to use XPF on a platform, such as XNA.

There isn’t actually much new in the codebase as a result but we have moved some code about and created a new assembly.  Alongside RedBadger.Xpf.dll you’ll now find RedBadger.Xpf.Adapters.Xna.dll.  RedBadger.Xpf no longer references any XNA assemblies, but obviously the adapter dll does.  (This structure is mirrored in the WP7 assemblies).

As it stands there is only one XPF adapter – XNA, but in time there maybe more whether they’re written by us or by you!  We'll be publishing the source code for the XNA adapter in the near future and giving  you a few more details on how you go about writing your own adapters, but in the mean time you’ll probably want to get the latest build, add a reference to the XNA adapter and fix up your code (should be fairly straight forward).

Other Changes (including Clipping)

Build 24 also brings with it clipping, which has meant a few changes to the way in which the SpriteBatchAdapter works.  We needed finer grain control over the SpriteBatch Begin and End calls (we use Scissor Testing to perform clipping which requires a change in RasterizerState) so you’re no longer responsible for calling SpriteBatch.Begin/End either-side of your call to RootElement.Draw.  To enforce this SpriteBatchAdapter no longer adapts SpriteBatch to ISpriteBatch via inheritance, but rather containment – so you physically can’t call Begin/End yourself.  This is consistent with the other adapters, so actually provides some nice usage symmetry too.

As a lot of the graphics related code has now been moved out of the main XPF assembly, we’ve re-organised our namespaces a bit.  Everything that was under Presentation has now moved up into the main Xpf namespace (Presentation is no longer).  We’ve also renamed XnaImage and ITexture2D to TextureImage and ITexture respectively.

As always, let us know how you’re getting on with XPF and thanks to all those who’ve provided feedback thus far, it’s been invaluable!

Tags , ,