Skinning guide: how to port a skin to MP2, or how "Titan" gets transformed (1 Viewer)

Status
Not open for further replies.

morpheus_xx

Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    Porting existing skins to MediaPortal 2

    Some first notes
    MediaPortal 1 already has a big number of good skins, and now with 1.3 beta there is the really great "Titan" skin. The idea of porting this skin to MP2 was born few days ago.

    I've talked with @joostzilla, he works with PhotoShop, drawing the controls and screens using vector graphics. This is already a very good starting point, as MP2 uses mainly vector graphics.

    But vector graphics are not the only thing which is done differently in MP2:
    The most important thing about the MP2 skinengine is not the possibility of vector graphics.
    It is the template based approach in combination with data binding allowing the skin designer to modify every aspect of how data is represented as he likes.

    (I will try to explain why a skin designer really should look into MP2 skin architecture).

    In the MP1 world, the sourcecode of a plugin dictates the GUI controls that has to be used - which greatly limits a designer in the choices how to display the information. In the MP2 world the source code merely provides objects with properties and the designer can chose any control he likes for it. Furthermore - (in example of a button) you are not limited to only providing a size, background texture, color and font size, you can define the way your control looks completely independent. (If you want your button to have a subtext below the main text or a flashing red underline, you can!).

    With MP1 - all skins are forced to have some common look and feel, because of the given set of controls and their possibilities to modify them. In MP2 - we have the chance to build completely different ways of presenting data.

    In MP2 skinning you can design the template of a button, export it as xaml, and use it in many different places inside the GUI - still having the chance to set different colors and sizes to parts of the button or animate certain elements differently. No need to exports multiple images for that - one resource. This will make the overall size of a skin a lot smaller and the memory consumption at runtime as well.


    For the ones who likt to follow the development on github, look here https://github.com/MediaPortal/MediaPortal-2/commits/FEAT_TitaniumSkin

    For all who like to discuss the contents of this guide and ask questions, please visit https://forum.team-mediaportal.com/threads/skinning-guide-discussion.114861/
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #2
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #3
    Let's start
    I started first experiments to import joost's psd files into Blend.

    • "In principle" it works to import the file, but the result is not the same as the source (not that I expected it...) See screen below, I think the main issue is different font rendering (width)
    • When I tried to import the "home" file with all layers, Blend crashed with a "OutOfMemoryException"
    • I think I get a first impression how you use the files: they contain all possible controls for different states, layers are temporary hidden and can be enabled to see how it will look when the control is shown
    View attachment 117300
    How will I continue?
    • First thing will be to find the most important components that build the layout: main panels, title, menu section, button styles...
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #4
    Started with some first changes:

    I do not start with the "Default" skin, but with a copy of "Reflexion" (https://github.com/MediaPortal/MediaPortal-2/commit/23d47cf84803aaff6fa9055360968ebea7284083). The main reason for this is, that the screens will be scaled to the resolution of the Skin that defines the <Screen> element. The good thing in MP2: you have only 2..3 Screens as master pages: change them once, results apply to all screens :) Even the Reflexion skin does only include the differences to the Default skin.

    So let's start:
    First I wanted to have the blue buttons on homescreen. I defined a new ButtonStyle, containing only a semi transparent rectangle with a border radius of "30".

    Then I'd like to have the bottom bar visible. I copied directly from the converted xaml into the "master_bare.xaml", which is the master of all screens. Place them once, use it everywhere.

    First 2 screens:
    View attachment 117309View attachment 117310

    I feel quite happy after few hours :)
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #5
    Next step:
    Adding a basic "glow" around the focused button in homescreen: Currently I simply put another Rectangle into the ControlStyle, which has an Opacity of "0" (full transparent). I've enabled the trigger that starts an animation when the button gets the focus. This animation increases the Opacity from 0 to 0.75.

    View attachment 117313

    The header label of the screen was shown in top right place. Now let's move it to bottom bar (here "choose series")
    View attachment 117314
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #6
    As next I wanted to have a background in the content screens, but not on home screen.

    For understanding the MP2 skin files, check the three main ones:
    • master_bare.xaml : this is the "overall master page" for everything
    • master_menu.xaml : this one includes the master_bare and defines styles for all "menu" based screens (in fact all execpt home)
    • master_homemenu.xaml: this one I use only for homescreen, it includes master_bare as well
    We work declarative manner here:
    In master_bare I added a

    <Rectangle DockPanel.Dock="Bottom" Fill="#FF000000" Opacity="0.749" Canvas.Left="50" Canvas.Top="340" Width="1824" Height="695" RadiusX="30" RadiusY="30"
    IsVisible="{Binding Source={DynamicResource EnableBackgroundPanel}}"/>
    Which does draw a rounded rectangle. Main part here is the IsVisible binding.

    Now, inside master_menu I add a resource:

    <ResourceWrapper x:Key="EnableBackgroundPanel" Resource="true" />


    And for master_homemenu I hide the rectangle using:
    <ResourceWrapper x:Key="EnableBackgroundPanel" Resource="false" />
    https://github.com/MediaPortal/MediaPortal-2/commit/f6d00d5d0eac39645c949e9afc2766a1350525df

    Homescreen still looks as in previous post, but now all other screens have a background:
    View attachment 117345
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #7
    To fill the home screen with images now? The current background manager does the following to get a matching background images:

    All workflow actions that appear in the menu are of type "ListItem". Such a ListItem for menus have a dictionary "AdditionalProperties", where the key "MenuModel: Item-Action" contains the WorkflowAction, which ActionId I use for image names. Sounds complicated, but isn't ;)

    Currently only one single image is exposed by BackgroundManagerModel. For our homescreen we need n images concurrently.

    This a good task for a so called ValueConverter:
    Code:
    namespace MediaPortal.UiComponents.BackgroundManager.Converter
    {
      public class ListItemActionIdConverter : IValueConverter
      {
        public bool Convert(object val, Type targetType, object parameter, CultureInfo culture, out object result)
        {
          result = null;
          ListItem listItem = val as ListItem;
          if (listItem == null)
            return false;
     
          object actionObject;
          if (listItem.AdditionalProperties.TryGetValue(BackgroundManagerModel.ITEM_ACTION_KEY, out actionObject))
          {
            WorkflowAction action = (WorkflowAction) actionObject;
            result = action.ActionId + (parameter != null ? parameter.ToString() : null);
            return true;
          }
          return false;
        }
     
        public bool ConvertBack(object val, Type targetType, object parameter, CultureInfo culture, out object result)
        {
          result = null;
          return false;
        }
      }
    }
    https://github.com/MediaPortal/MediaPortal-2/commit/83a023ec018469434261ac2b2520418367c79f31

    In my template for the "MainMenuItemDataTemplateHover", I now can use the ListItem (== menu action) and use my new ListItemActionIdConverter:
    <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Width="580" Height="244" Stretch="UniformToFill"
    Source="{Binding Converter={StaticResource ListItemActionIdConverter}, ConverterParameter=.jpg}"/>
    It extracts the ActionId from the item and appends my given ".jpg" to build a valid image filename.
    https://github.com/MediaPortal/MediaPortal-2/commit/ea5ae8978aa9e1381dbe7f316cb3256076911bac#L2R93

    The converter is added to the background manager plugin. Nothing needed to be modified in the SkinEngine.
    View attachment 117346

    What you see here are still the Reflexion images, and I left the rounded corners away. This is a new topic...
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #8
    Some smaller tweaks are done on the homescreen part. While in the image above there were some minor glitches: i.e. the semi-transparent overlay in the buttons where not exactly fitting the whole button dimension.

    I've tweaked this a bit by moving button background (semi-transparent blue) to the ListItem style: https://github.com/MediaPortal/MediaPortal-2/commit/87f8ae7ce5f49a5df3da2a1cd8f23c882cd00fd0

    Also the default font got changed to "Titan":
    https://github.com/MediaPortal/MediaPortal-2/commit/8d42140335bc478560add74201513ca38ed0c8eb

    Next I wanted to replace the Reflexion based hover images by the Titan ones:
    https://github.com/MediaPortal/MediaPortal-2/commit/424b5b41896b1b2bd832ab7945583b03377aeab4

    And as you can see I also added the player controls to homescreen.

    At this time you can already see some differences to MP1: for MP1 there is only one player that can be active. In contrast, MP2 can handle 2 players concurrently (hint: soon it can handle unlimited players :whistle:). For now this means, we need to reserve space for 2 player controls.

    Also in MP2, this control is not only a "progress indicator" but the way to control players (start/stop, pause, skip...). Good, we can save all the controls from the MP1 topbar...

    If you try yourself, you will also find that the home menu screen in current MP2 state is working differently: while MP1 shows 6 items on screen and allows "paging" to right for more screens, MP2 does show all menu items in a WrapPanel, which allows scrolling vertically.

    It does not mean that it can't be changed, but for this phase of development I'll keep it simple.

    07_homescreen_new_hovers.jpg
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #9
    Now I'll take care for the player control style.As template I only had the final raster image available, so I thought to draw them in vectors again.

    In princple the style I've redone is simple:
    • One rounded rectangle as background
    • One rounded rectangle using a transparency gradient as overlay
    08_drawing_template.jpg


    Blend creates those xaml code for me:
    Code:
            <Rectangle Fill="#FFD2D2D2" Height="140" Margin="449,292,851,0" Stroke="Black" VerticalAlignment="Top" RadiusX="30" RadiusY="30" StrokeThickness="0"/>
            <Rectangle Height="140" Margin="449,292,851,0" Stroke="Black" VerticalAlignment="Top" RadiusX="30" RadiusY="30" StrokeThickness="0">
                <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#46FFFFFF"/>
                        <GradientStop Color="#945E546A" Offset="0.874"/>
                    </LinearGradientBrush>
                </Rectangle.Fill>
            </Rectangle>

    I placed this into the "OtherControlsOverrides.xaml":
    Code:
                <!-- Background of player control panel-->
                <Rectangle x:Name="PCBackground" Grid.ColumnSpan="2" Fill="{ThemeResource PlayerControlBackgroundColor}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RadiusX="30" RadiusY="30" />
                <Rectangle Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RadiusX="30" RadiusY="30" >
                  <Rectangle.Fill>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                      <GradientStop Color="{ThemeResource CurrentPlayerControlBackgroundColor2}" Offset="0"/>
                      <GradientStop Color="{ThemeResource CurrentPlayerControlBackgroundColor3}" Offset="0.874"/>
                    </LinearGradientBrush>
                  </Rectangle.Fill>
                </Rectangle>
    Things to note:
    • I removed the margin from Blend (it positioned the item on the screen, here it's placed relative)
    • I replaced the fixed Width and Height by HorizontalAlignment="Stretch" VerticalAlignment="Stretch", this way my template is as big as the content requires.
    • I gave the rectangles a name, like x:Name="PCBackground"
    • The color constants are now replaced by "{ThemeResource PlayerControlBackgroundColor}". This way there is a color constant taken from our "colors.xaml" resource file. This has a simple reason: when you want to create a new color theme, you simply copy the "colors.xaml" and change few color constants. So creating blue, yellow or pink controls is just a matter of one color code.
    Extract from colors.xaml:
    Code:
      <ResourceWrapper x:Key="PlayerControlBackgroundColor" Resource="#FF3F4149"/>
      <ResourceWrapper x:Key="CurrentPlayerControlBackgroundColor1" Resource="#FFD2D2D2"/> <!-- Used as background fill for current player -->
      <ResourceWrapper x:Key="CurrentPlayerControlBackgroundColor2" Resource="#46FFFFFF"/> <!-- Used as gradient color overlay for all cases -->
      <ResourceWrapper x:Key="CurrentPlayerControlBackgroundColor3" Resource="#945E546A"/> <!-- Used as gradient color overlay for all cases -->

    Now again a bit of MP2 player theory: because you can have multiple active players, you need to separate their states. For this part the important state is the "CurrentPlayer": only one player is the "Current" one and handles the input (Pause, Play, Skip,...).

    To make them appear in a different style, we use a DataTrigger, that changes the "Fill" property of the "PCBackground" rectangle. That what's the names are for...
    Code:
              <ControlTemplate.Triggers>
                <Trigger Property="IsCurrentPlayer" Value="True">
                  <Setter TargetName="PCBackground" Property="Fill" Value="{ThemeResource CurrentPlayerControlBackgroundColor1}"/>
                </Trigger>
              </ControlTemplate.Triggers>

    As result you can see following examples:
    1) Only one video player active
    08_playercontrol_single.jpg
    2) Primary Video Player + Secondary Video Player in PiP mode. The "Current Player" is the first one
    08_playercontrol_PiP.png
    3) Primary Video Player + Secondary Audio Player. The "Current Player" is the second one
    08_playercontrol_video_audio.jpg

    Changes done in https://github.com/MediaPortal/MediaPortal-2/commit/eb578cee3d73ac01846a8bc0deacae01854ff2ee
     
    Last edited:

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    • Thread starter
    • Moderator
    • #10
    The homescreen looks quite nice already. There are mainly few things missing:
    • rounded buttons (currently postponed because of an issue with opacity masks)
    • shadows (currently not possible, but will be implemented by shader effects later)
    • power menu (or normal buttons)
    09_homescreen.jpg


    I changed all menu screens to use a hidden menu now:
    https://github.com/MediaPortal/MediaPortal-2/commit/2d21b2d781dacc3c597f0b44ff4e9e8dd1f25739
    Besides of moving some controls around, I mainly created a new style for the menu. It slides in from left side, triggererd by "Info" key, or button click ("menu")
    10_audio_list.jpg



    Usually we have only one (or few) general button style defined. I decided to add a new one, especially for the "hidden menu".
    11_audio_list_hiddenmenu.jpg


    Next part will be the styling of the main listviews.
     
    Status
    Not open for further replies.

    Users who are viewing this thread

    Top Bottom