Saturday, August 21, 2010

Friendly Assemblies in C#

While looking over Reflector-ed Microsoft code I noticed an attribute called FriendAccessAllowed. I googled a little and I've come up across something called Friendly Assemblies. Basically you want that your code marked as internal be visible to other assemblies that you specify. This way you restrict access for other people, but you don't need to place all your code into a huge assembly.

Microsoft tells us that to do that for .NET you need to use InternalsVisibleToAttribute to make assemblies be friends in either a signed or an unsigned way.

All nice and all, but there is no mention of this FriendAccessAllowedAttribute class. All I could find is a Microsoft patent called Logical Extensions to Intermediate Code, which says extend the runtime's notion of friend assemblies with a "FriendAccessAllowed" attribute, and only include internal methods marked with this attribute in the reference assembly (instead of known implementations in which all internal methods are included in the assembly).. In other words, specify explicitly which of the internal members you want exposed to your friends.

There is another question about this on StackOverflow, which says as much, as well, but nothing actually usable.

As far as I can see, Microsoft uses this in the WPF and Silverlight frameworks only and the funny thing is... the attribute is internal. :)

Defining a theme/skin for a control library in WPF

If you search the net for a skinnable application, you get a lot of answers and pages that seem to hit the spot right on. If you are looking for a skinnable control library, though, the hit count drops considerably. This post is about my adventures with resource keys and the solution for a problem that has plagued me for more than a day of work, plus some weird behaviour that I have as yet no explanation for.

The article is pretty long, so here is the short and dirty version:
  • Do not use Colors as dynamic resources, use Brushes
  • If you want to use resources from a theme dictionary outside the assembly, you must give them keys of the type ComponentResourceKey
  • The type you use in the constructor of the ComponentResourceKey class or in the markup extension of the same name must be in the same assembly where the resource is!

The scenario is as follows:
  • there is an application that needs to change some of its visual characteristics dynamically during run time
  • the application uses a custom control library
  • other applications/modules should use the same themeing mechanism
  • other applications will use the same control library

The solution seemed simple enough:
  • create a static class to hold the string keys for the resources I want to define dynamically
  • create a shared resources dictionary in the controls theme, using those keys
  • use the shared dictionary in the controls theme
  • create another shared resources dictionary in the applications, or use only the ones already defined in the control library
  • use the application shared dictionaries in the application styles
  • programatically add/remove resources directly in Application.Current.Resources to override the already defined resources

I have tested this solution in a not very thorough manner and found it working. Of course, some of the problems needed solving.

The first issue is that theme level resources are not found from outside the assembly unless defined using a ComponentResourceKey as the key of the resources. This special class receives two parameters in the constructor: a type and an object that is a "regular" resource key. So instead of using a string, as one would probably use in an application style, you use a component resource key that receives a type and that string. A small test confirmed that a resource is not found at the application level using FindResource if only defined with a string as key and that it is found if using a ComponentResourceKey.

The second issue was that in order for a resource to be dynamically changed at runtime it needed to be defined as a DynamicResource, not a StaticResource which is only resolved at compile time. Not a huge problem. However, if one has defined some brushes in the control library and then referenced them in all the styles, then it would also work to redefine those brushes to use colors dynamically, and then all one has to do is change the colors. That would also prove advantageous if one needs a variety of brushes using the same colors, like gradients or some lighter version of the same color.

This leads to Problem number 1: Dynamically changing Color resources worked for foreground brushes, for background brushes, but not for border brushes! So you have a textbox and you define Background, Foreground and BorderBrush properties using StaticResource on brushes that themselves define their Color as a DynamicResource. You change the colors (adding new resources at the application level of the type Color) and you see the Background and Foreground changing, but the border staying unchanged.

I have no idea why that happened. Some information that I got researching this problem was related to Shared resources, but changing the shared status of brushes or even colors to true or false did not change anything. Another idea was that his was related to their Frozen status but, as there was no difference between the Foreground and BorderBrush brushes (I even used the same brush at the same time on both properties), I've decided that it wasn't the case.

BorderBrush is a dependency property belonging to the Border element, while Foreground and Background belong to the TextElement and Panel elements, respectively, and other elements add themselves as owners to them. In the case of the Border element that I have tested this weird behaviour on, BorderBrush is its own dependency property, while Background is the Panel.BackgroundProperty. I also thought that it may have something to do with FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender, but both properties are registered with this flag.

After some searching, I found that the Border element caches internally Pen objects that are used to render the different border sides. They use the same brush as the border, though, and so, even if this is the best candidate for the cause of the problem, I still don't know what the hell was going on.

The solution for this problem was (to my chagrin) to use the brushes themselves as dynamic resources. Well, it was a setback, seeing how the resources I want to change are colors and now I am forced to create brushes and, thus, stain this process with the responsibility of knowing what kind of brushes are needed for my controls and applications, but I could live with it. After all, that was all WPF stuff, so I could separate it at least from the static class holding the keys of the characteristics I wanted to change dynamically.

Problem number 2: using as a key in XAML a class with a long name which uses a constructor that receives a type and a static constant/property of a class is ugly and unwieldy. The solution for this problem was to create another static class that would hold the keys for the brushes. Each brush would have a property in the class that returns a ComponentResourceKey object that uses the classes own type as the first parameter and the constant string key from the static string key class.

That effectively changes stuff looking like {DynamicResource {ComponentResourceKey TypeInTargetAssembly={x:Type UI:ResourceScheme},{x:Static UI:ResourceScheme.ControlBackgroundKey}}} to {DynamicResource {x:Static WPF:ThemeResources.ControlBackgroundBrushKey}}. Still a mouthful, but manageable.

Problem number 3 (the big one): it doesn't work! The brushes I so carefully created in the theme are not getting set in the controls, not the mention the application. What confounded the issue even more is that if I changed DynamicResource to StaticResource in the control templates I would see the brushes rendered correctly. I wouldn't be able to change them dynamically afterwards, but how come StaticResource works and DynamicResource doesn't!? Stranger still, adding/removing resources with the same key in the application resources dictionary (the mechanism that was supposed to dynamically change the aspect of the application) worked! Everything was working perfectly, and only the default brushes defined in the theme were not loaded!

The solution for this was (after hours of trial, error, googling, suicidal thoughts and starting all over again) to use a type from the control library in the ResourceComponentKey constructor! You see, I had placed both static key classes in a separate assembly from the control library. Moving the WPF related resource key class in the control library fixed everything!

Now, you may be wondering why that worked, and so do I. As I see it, if you define a template and a brush in a theme and the template is loaded and applied, then the brush should also be loaded. If FindResource did not find the brush, then it must be that either the brush was not loaded due to some internal requirements of the ResourceComponentKey class or that it was loaded and then the key I was using was different from the one I was using when asking for it or, as Akash Kava tried to explain to me on StackOverflow, it will only find in the resource dictionaries of its own logical parental tree.

I have dismissed the second option, as the ComponentResourceKey has an Equals override that simply compares type and key. There cannot be two instances of the same type and the key is a string constant, so there should be no ambiguity on whether two resource keys are equal.

What remains are that either the ComponentResourceKey class messes things up or that the resources using resource keys are placed in "logical trees" based on the target type of the ComponentResourceKey. I have looked for the usages of the ComponentResourceKey class and all I could find was something in a BaseHashHelper that seemed related to ItemsControl or CollectionView, so I don't think that's it. I also looked at the implementation of FindResource, but found nothing that I could understand to cause this.

As a funny side note, as I was going about this task I was trying to get inspiration from the way the SystemColors class worked. The resource keys related to colors that were returned were not of the type ComponentResourceKey, but of SystemResourceKey, both inheriting from ResourceKey nonetheless. I have noticed no significant piece of code in the (of course internal) SystemResourceKey class, however I did find code in FindResource that checked if the key is of type SystemResourceKey and did something with it. Nice, Microsoft! However, that was not the cause of the problem either.

After knowing what to look for, I did find on the Microsoft article about the ComponentResourceKey markup extension that The TypeInTargetAssembly identifies a type that exists in the target assembly where the resource is actually defined. In the article about the ComponentResourceKey class, they say If you want an easily accessible key, you can define a static property on your control class code that returns a ComponentResourceKey, constructed with a TypeInTargetAssembly that exists in the external resource assembly, and a ResourceId. Too bad they hid this information in the Remarks section and not in the definition of the Type parameter.

Congratulations if you have read so far! You must be really passionate about programming or desperate like me to find an answer to these questions. I hope this article has enlightened you and, if not, that you will find the answers and then get back to me :)

Saturday, August 14, 2010

Starcraft II - Wings of Liberty

I have been waiting for this game for 12 years, just like everybody else, but not for the usual reasons. I like the Blizzard stories. I liked the Starcraft tales of the first game and I absolutely loved the Warcraft III plot. I was expecting something glorious this time. Well... I was kind of disappointed. The story is pretty linear, with cowboy characters and dialogues seemingly stolen directly from the propaganda in Starship Troopers.

But first, a word from our sponsors :). The campaign has a secret mission. Read about it before starting the single player game. So even if you have a Queen of Blades nagging you talking a walk around the base and buying her Xel'Naga artifacts, don't rush the Media Blitz mission. ;)

I have this old Sempron 2500+ with 1Gb of RAM. The game, at the lowest possible settings, was snail paced. One needs memory for this baby. I am not blaming Blizzard for my laziness in buying a computer, but it seemed to me that all the slowness came from reasons that could have been addressed. For example the game (as it should) remembers correctly every keystroke and mouse click in battle. However, in the HUD or in the game menu, one has to wait for the buttons to light up before clicking, and then keep pressing until the button lights up the second time. In game, the greatest slowness came from special effects that were not related to the game play. I understand a suspended nuke over a flowing lava fountain might exert the CPU of a computer, but the animation itself could have been scaled down to an animated GIF for crying out loud. The cinematic animations were pretty nice, and I loved how when I ran out of resources the film would not freeze, instead the characters would wait for the next part of the dialogue, breathing and moving their eyes. But still, since there is no interaction whatsoever from the user, can't you precache it into a movie? One that can be played on any computer and has the video in sync with the audio?
So yes, the game is running slow on my computer, but I feel that it could have worked a lot better with only some minor tweaks of the in game interface.

The in game interface is pretty nice, completely 3D and the map itself is 3D and some units (a precious few) can take advantage of that, like hopping jet packed soldiers or air-ground transforming machines called the Vikings). However, the game play is almost identical to the first game, so the 3D feels kind of pointless. There are camera zoom and rotation abilities, but the zoom out is limited to a pretty low setting and the zoom in is kind of pointless unless you have female units to properly look at :)

The units of the game are interesting enough. The old units have been morphed, replaced, removed, and new units were added. For the humans are multiple types of turrets, including machineguns on the bunkers, air units dropping turrets and a special mind control tower that permanently captures zerg units. The Goliaths are still there, but also a more heavy, ground focused Thor unit is available. There are multiple soldier units other than the Marines and Firebats, like hopping and grenade launching units. It is funny though, most human soldiers and vehicles are focused on attacking only ground units. The air units have been reinvented. There are small troop carriers that can heal units, really big Hercules troop carriers, the Battlecruisers have an upgrade that allows them to attack air units with missiles, the Valkirie is gone, but it was replaced by the Viking, a sort of transformer unit that can fly and attack air units or transform into a walking robot that attacks ground units. There are two types of science vessels and they repair mechanical units instead of firing EMP pulses. There are two types of ghosts, too.

The Zerg have been transformed, too, as well as the Protoss, but I can't really address this issue until I play some multiplayer games to see it from all perspectives. And yes, I guess you already know by now, but I will tell you anyway: after 12 years of waiting, you only get the human campaign. The Zerg follows, then the Protoss, probably in expansions to the game.

There is a mini campaign with the protoss, where any two templars (dark or light) can be morphed into an Archon, but I have seen no trace of the Dark Achon. I really loved that unit. I hope they didn't remove it. Also the zerg overlords need to transform into Overseers in order to be observers; they lose the ability to transport and to pour creep from the air (yeah, really cool) and instead have the ability to spawn banelings, creatures that attack ground units and transform into the same low level unit they encounter, like a zealot or marine or something like that. I know this because, while missing the Dark Archon, I really loved the human zerg capturing beacon tower :) I haven't seen any lurkers, either. I liked them, too. Instead there are some walking buildings that burrow in the creep and become normal ground turrets. Maybe that's the only way to build ground turrets now.

There were some real innovations to the game. The units that can hop to high ground is one of them. The way SCVs are repairing nearby structures and mechanical units without someone having to tell them to do it is something that I really liked. Also you can place a building over ground covered by your own units and they will just move out of the way. You also get useful alerts, like idle SCVs. I liked that as well. There is a special human building where one can call mercenaries, specialized unit squadrons that have extra health and deal extra damage. Also, in the story, there are research points that you earn and use them to select one of two choices in a list of pairs of technologies. For example you can choose to slow zerg units instead of capturing them with the beacon, you can choose stronger bunkers instead of machine gun equipped, etc.

That being said, there are still ridiculous ways in which groups of units interact. You can't easily tell a group of medics to accompany and repair a marine unit. If you select them all and attack, the medics will heal the marines, but if you tell them to move, they won't! If you select multiple air and ground units, there is no way to tell them to clump together. The air units will just go over and die, while the ground units use the scenic route. Units do move out of the way of other moving units, but only for a while, sometimes getting into infinite loops. As in the previous game, the forward line of an attack group doesn't know to move a little forward to let the back like be in attack range and heavily hit units don't really have any way to retreat while others are covering.

So yes, I guess one can enjoy the game as the one before, but I am the kind of guy who likes automatic transmission, cars that park themselves and, hopefully in the near future, drive themselves. I would have created an entire option panel that described how units ought to behave.

Now for the story. Spoilers alert! If you want to play the game and see the story unfold, stop reading!.

The sector is mostly occupied by humans. Mengsk has overthrown the government and became emperor, one that is even more brutal and oppressive than the one before. In the process he betrayed his partners: Jim Raynor and Sarah Kerrigan. Raynor is now the leader of the resistance, while Sarah Kerrigan was abducted by the Zerg, transformed into an infested version of herself and has since taken over as the leader of the Zerg, after the Protoss have destroyed the Overmind.

So Raynor is doing mischief trying to get to Mengsk, while the Zerg appear in the sector and start taking over human worlds. The Protoss couldn't care less. They occasionally purge worlds of Zerg (by destroying the entire planet, inhabited or not) or hold up in sacred locations, bent on stopping anyone from taking their precious holy artifacts.

You see, the Protoss are believers in the Xel'Naga, their creator gods. Well, what do you know? The Xel'Naga actually exist, they created the Protoss and the Zerg and now they are returning. Looking like hybrids of Protoss and Zerg, they have shields, they can heal really fast and can corrupt zerg units into becoming their slaves. Probably tired of waiting 12 years to get the second Starcraft game, they are pretty pissed and want to corrupt all the Zerg into destroying all life in the sector, then commanding them to kill themselves, thus ending all life.

Raynor is here to save the world so, with a little premonitory help from his friends Zeratul and Tassadar, he sees what the Xel'Naga plan and sees that the entire future depends on him NOT KILLING Kerrigan. She alone can do something against the Xel'Naga. We also learn that the Overmind was under the control of the Xel'Naga all the time and it created the Queen of Blades from Kerrigan as a solution to its enslavement, thus proving great courage. Poor Overmind :'(

Therefore, the purpose of this campaign is to get to the Queen of Blades and use an ancient Xel'Naga artifact to purge the Zerg out of her. Badly enough, Infested Kerrigan is not the sexy babe she was in the first franchise, instead she is some afro-mongoloid with bad skin and shiny eyes, so I was highly motivated to see her brought back to normal.

The story has three choice points, which can slightly alter the plotline. One is when the world where you relocated some humans you saved gets infested. Protoss units come to purge the world and you can have the choice of purging the world yourself or fighting the Protoss to stop them. Later on, one can choose whether to use Ghosts or Specters. Specters are a slightly insane version of the Ghost created by one of Mengsk's secret programs. Then, on Charr, you can choose to destroy the Zerg Nydus worms or their air units. I was also mentioning a secret mission, found if destroying a conspicuous building in the Media Blitz mission.

Obviously, I purged the humans and kept the spectres. I killed the Nydus worms, too, but I think that's clearly the more sensible solution when you have the capture beacons.

!!! Uberspoilers !!!

The campaign ends with Raynor untransforming Kerrigan, killing Tychus who has been sent to kill her, probably by some Xel'Naga influenced human group (I dare say it would have been stupid for Mengsk to ally with the Xel'Naga, but he is a likely culprit) and purging Charr of all Zerg.

Ok, there are also some cheats that can help you end the game faster. You won't get any achievements if you use them, but then again, you need to play the uncracked version to use achievements, so the hell with them.

Wednesday, August 11, 2010

Everything you want to know about Pac-Man!

A pac-man file
You know when you are playing some famous game you get millions of pages discussing strategies and solutions to in-game problems? Well, if you think about it, all those pages could be brought together and bound in something like a book. Why not write StarCraft for Dummies or Professional Warhammer 40000? And with that in mind, how would you feel about a book whose entire purpose is discussing Pac-Man?

Curious yet? You can check it out here! It writes about the algorithms used in the game, the tips and tricks for playing, even the different personalities of the four killer ghosts! Everything complete with pictures, diagrams and YouTube videos!

Monday, August 02, 2010

Adding triggers to WPF User Control

I've hit this issue a few times, always forgetting the solution afterwards. It also is a problem that doesn't feel like it should be there. It regards using User Controls in WPF, those with attached XAML files, and wanting to add some triggers that affect some of the elements declared in the XAML.

The problem is that if you want to add a trigger in the UserControl.Triggers collection you get a run-time error telling you only EventTriggers are available in that section. If you try an ugly use of the style triggers collection liks this: UserControl.Style -> Style -> Style.Triggers, you get a compilation error saying you can't use TargetName in a Style setter.

There are two solutions, one uglier than the other. One is to use a multi binding to add all the things that affect a property in a setter. Of course, you need a converter class for each one. Yuck! The other solution is to add a setter in the style of the element you want to change, therefore eliminating the need for the TargetName attribute. This is what I use when a trigger is badly needed. I know, fugly.

Update: I have tried to create an attached property that would act like a control trigger collection that would accept any type of trigger. While that was not a problem, I got stuck at the point where every property and value had to be fully qualified, making the style with trigger option look more attractive than this. It appears that the XAML reader itself handles triggers differently and the way it qualifies property names is hardcoded somehow. If anyone gets a handle on how to solve this get a free beer from me :)