Skinning contest: One month to go (1 Viewer)

infinite.loop

Retired Team Member
  • Premium Supporter
  • December 26, 2004
    16,163
    4,133
    127.0.0.1
    Home Country
    Austria Austria
    Yeah. Particle Effects are gonna be real useful in MP :rolleyes:

    Pixel shaders could be used for almost anything. Not just particle effects. Blur, grayscale, water like animation... list is endless
    You could also create awesome, dynamic - animated backgrounds with particle effects. Inside MP2.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    Oh that is sad...
    Can you give me a hint how to realize this? Because the ellipses have different blur effects.

    I attached the source of my WPF application, but the source is very ugly, so you are warned^^

    Finally I had the time to try your WPF application.

    Well, I would say the problem that you don't have access to the MPF elements from code is not such a problem. I would create 10 or 20 or so particles on the canvas and bind it to position vectors which come from a model. Those position vectors must be changed by the movement algorithm.

    I cannot tell you how you can create the particles; Baboonanza is a much better source for that question.

    Yes, I already thought about it... But as Baboonanza said and I think he's right, it should be implemented into the skinengine.
    So, the question is: Does it make sense to spend time on that if it should be integrated into the skinengine anyways?
    Sure, it would be a proof of concept and maybe I will try it^^ But it shouldn't be the final solution.

    By the way: Does anyone know where the MP2 Controls are registered in the skinengine? I only can find ellipse.cs etc. but no connection to these files oO Maybe I'm just blind...
     

    Albert

    MP2 Developer
  • Premium Supporter
  • February 18, 2008
    1,297
    1,130
    45
    Freiburg im Breisgau, Germany
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    Registration.cs is the registration class for MPF classes.
    But like "normal" XAML, our XAML also provides the feature to register custom classes/assemblies with own controls/brushes/whatever. See file OtherControls.xaml for example; it contains an import of non-MPF-classes (which are also located in the SkinEngine, but need to be imported separately).
     

    Baboonanza

    Retired Team Member
  • Premium Supporter
  • February 5, 2010
    143
    57
    North London
    Home Country
    United Kingdom United Kingdom
    Re: AW: Skinning contest: One month to go

    Yes, I already thought about it... But as Baboonanza said and I think he's right, it should be implemented into the skinengine.
    So, the question is: Does it make sense to spend time on that if it should be integrated into the skinengine anyways?
    Sure, it would be a proof of concept and maybe I will try it^^ But it shouldn't be the final solution.
    I've already started coding a ParticleSystem element, but for various reasons my testing time is much more limited than my coding time and I have more urgent debugging to do (for video playback) so it may be little while before it's ready. I'll let you know. I might put it together with my EffectBrush (a brush that allows use of custom shaders with XAML defined parameters) into a SkinEngine Extension plugin which can then be added to core later if necessary.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    Albert
    thanks for your tips, I will try to get it work, even it is not necessary, but I just want to learn MPF^^

    @Bamboonanza
    I'm glad to hear^^

    @All
    I tried to understand what the following is for:

    ResourceWrapper, LateBoundValue, BindingWrapper
    WPF: - MPF: <ResourceWrapper x:Key="..." Resource="abc"/>
    <LateBoundValue x:Key="..." Value="{Binding ...}"/>
    <BindingWrapper x:Key="..." Binding="{Binding ...}"/>

    Maybe somebody could give me some more details on this ;)
    I tryed to understand it on the Playlist example... because in a Playlist there must be the possibility to add Items to the ListView Element dynamicly.

    Code:
    <ListView Style="{ThemeResource PlaylistListViewStyle}" ItemsSource="{Binding Items}"
                  HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                <ListView.Resources>
                  <Command x:Key="Select_Command" Source="{StaticResource ShowPlaylistModel}" Path="Play"
                      Parameters="{LateBoundValue BindingValue={Binding}}"/>
                </ListView.Resources>
              </ListView>

    But I dont really understand how it is done
     

    Albert

    MP2 Developer
  • Premium Supporter
  • February 18, 2008
    1,297
    1,130
    45
    Freiburg im Breisgau, Germany
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    Hehe FreakJ, here you're crossing the border to the really complicated MPF elements.

    Although ResourceWrapper is quite easy, the others aren't.

    ResourceWrapper

    ResourceWrapper is - as its name says - simply a wrapper for other elements. It is useful in ResourceDictionaries:

    Code:
    <SomeUIElement>
      <Resources>
        <ResourceWrapper x:Key="BlackColor" Resource="#FF000000"/>
      </Resources>
    </SomeUIElement>

    Every element/resource/whatever can be wrapped in a ResourceWrapper but it is only really needed for elements which don't have an XML element representation. For example, there is no "constructor" element for a simple string. That means, you cannot write <String>HelloWorld</String>, because there is no <String> element. The same with color values like in the example above. The ResourceWrapper can be used to make such elements available in resource dictionaries.

    LateBoundValue

    To understand why LateBoundValue is needed, you need to know how the XAML engine processes the files, which is not so easy. When the engine uses a resource provided by a ResourceWrapper, that resource is extracted from the wrapper instance at once. For example if you have a property assignment SomeColor="{StaticResource BlackColor}", the BlackColor resource from above (the string "#FF000000") will be used rather than the enclosing ResourceWrapper. Then, the string is converted into a Color object and assigned to the SomeColor property.

    But when using bindings, you sometimes don't want that the value is extracted at once.
    Here comes an example. In fact that is the common usage scenario for LateBoundValues:

    Think of a <Command>, maybe a command of a Button:
    (the following code will not work)
    Code:
    <Button>
      <Button.Command>
        <Command>
          <Command.Parameters>
            <Binding Source="..." Path="..."/>
          </Command.Parameters>
        </Command>
      </Button.Command>
    </Button>

    Internally, the Parameters property of the command is just a collection, so the XAML parser has no chance to bind the given Binding to some property. So the parser needs to evaluate the binding at once, which will probably fail, and thus you only get a null value as parameter.

    To solve that problem, we have LateBoundValue:
    (works well)
    Code:
    <Button>
      <Button.Command>
        <Command>
          <Command.Parameters>
            <LateBoundValue>
              <Binding Source="..." Path="..."/>
            </LateBoundValue>
          </Command.Parameters>
        </Command>
      </Button.Command>
    </Button>

    Here, the XAML parser can bind the binding to the Value property of the LateBoundValue instance. When the command is executed, it explicitly converts all parameters of type LateBoundValue to their contained Value resource.

    BindingWrapper

    The last class you mentioned is BindingWrapper. I won't describe it here completely because you'll only use it if you are a "master of MPF". Like ResourceWrappers, which are used to pass resources to DynamicMarkupExtensions, BindingWrappers are needed to pass custom binding instances to PickupBinding markup extensions. You can see that in the DefaultSingleMarkableTreeItemContainerStyle, defined in OtherControls.xaml.

    I hope I could make things clearer. Please ask if you still have questions.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    First of all thanks for your detailed help ;)

    At first I tried to understand the ResourceWrapper, but I still don't get the point oO
    In the file ShowPlaylist.xaml you are using the following line (for example):

    Code:
    <ResourceWrapper x:Key="Contents_Element">

    I I don't find any reference in a .cs file to this "resource"... Also there is no reference in any .xaml file to "Contents_Element".

    I think your example above make sense... If I'm right the example above should work like this (the <SomeUIElement> is maybe a bit confusing.., but I know that it is a placeholder for an element^^ But it can destroy my theory xD):

    Code:
    <SomeUIElement>
      <Resources>
        <ResourceWrapper x:Key="BlackColor" Resource="#FF000000"/>
      </Resources>
    </SomeUIElement>
    
    <label color="BlackColor" content="string" />

    I didn't tried it yet, just tried to understand it in theory, because I'm still struggling at a more basic point and think I should understand this first before I will come to this back, but later on more on my little second problem^^

    But what is the exact function of the ResourceWrapper in the ShowPlaylist.xaml file? Maybe I get the point if you could explain it ;)
    Sure, you told me that I can use it if there is nor xml element like <string>, but why do you need it in the ShowPlaylist.xaml?! You have a <grid> element, which is "wrapping" all the stuff...

    //------------------

    Now to my little second problem, which is a bit more basic^^

    First of all my xaml file:

    Code:
    <DockPanel Name="FastParticleBackground.Window1"
    xmlns="www.team-mediaportal.com/2008/mpf/directx"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Context="{Model Id=5726DA5A-70D5-458f-AF67-611293D97912}" LastChildFill="False">
        <Grid>
            <Grid.Background>
                <RadialGradientBrush Center="0.54326,0.45465" RadiusX="0.602049" RadiusY="1.02049" GradientOrigin="0.4326,0.45465">
                    <GradientStop Color="#57ffe6" Offset="0"/>
                    <GradientStop Color="#008ee7" Offset="0.718518495559692"/>
                    <GradientStop Color="#2c0072" Offset="1"/>
                </RadialGradientBrush>
            </Grid.Background>
            <Canvas x:Name="ParticleHost">
                <Ellipse RenderTransformOrigin="0.5,0.5" Width="5" Height="5" Fill="White">
                    <Ellipse.RenderTransform>
                        <TransformGroup>
                            <TranslateTransform X="{Binding TranslateTransform0_X}" Y="{Binding TranslateTransform0_Y}"/>
                        </TransformGroup>
                    </Ellipse.RenderTransform>
                </Ellipse>
            </Canvas>
            <Label Content="{Binding HelloString}" Margin="10"
            HorizontalAlignment="Left" VerticalAlignment="Center"/>
        </Grid>
    </DockPanel>

    the model.cs (still ugly stuff, I know, but I'm still in the try and error state^^ so there is no chance of a clean code xD)

    Code:
    #region Copyright (C) 2007-2010 Team MediaPortal
    
    /*
        Copyright (C) 2007-2010 Team MediaPortal
        https://www.team-mediaportal.com
    
        This file is part of MediaPortal 2
    
        MediaPortal 2 is free software: you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        MediaPortal 2 is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU General Public License for more details.
    
        You should have received a copy of the GNU General Public License
        along with MediaPortal 2.  If not, see <http://www.gnu.org/licenses/>.
    */
    
    #endregion
    
    using MediaPortal.Core.General;
    using MediaPortal.UI.Presentation.Models;
    
    using MediaPortal.UI.SkinEngine.MpfElements;
    using MediaPortal.UI.SkinEngine.SkinManagement;
    using MediaPortal.UI.SkinEngine.Xaml;
    using MediaPortal.UI.SkinEngine.Xaml.Interfaces;
    using MediaPortal.UI.SkinEngine.Controls.Visuals;
    using MediaPortal.UI.SkinEngine.MpfElements.Resources;
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    
    using System.Windows.Threading;
    //using System.Windows.Media;
    using System.Windows.Media.Media3D;
    using System.Windows.Media.Effects;
    using System.Windows.Shapes;
    using System.Collections;
    using System;
    using System.Windows;
    
    namespace Models.HelloWorld
    {
      /// <summary>
      /// Example for a simple model.
      /// The screenfile to this model is located at:
      /// /Skins/default/screens/hello_world.xaml
      /// </summary>
      /// <remarks>
      /// <para>
      /// Models are used for providing data from the system to the skin and for executing actions (commands)
      /// which are triggered by the Skin, for example by clicking a button.
      /// </para>
      /// <para>
      /// All public properties can be data-bound by the skin, for example the <see cref="HelloString"/> property.
      /// Note that properties, which are updated by the model and whose new value should be propagated to the
      /// skin, must be backed by an instance of <see cref="AbstractProperty"/>. That instance must be made available
      /// to the skin engine by publishing it under the same name as the actual property plus "Property", see for example
      /// <see cref="HelloStringProperty"/>.
      /// </para>
      /// <para>
      /// You can also consider to implement the interface <see cref="IWorkflowModel"/>, which makes it
      /// possible to attend the screenflow = workflow of the user session. When that interface is implemented and this
      /// model is registered in a workflow state as backing workflow model, the model will get notifications when the
      /// GUI navigation switches to or away from its workflow state.
      /// </para>
      /// <para>
      /// To make an UI model known by the system (and thus loadable by the skin), it is necessary to register it
      /// in the <c>plugin.xml</c> file.
      /// </para>
      /// </remarks>
      public class Model
      {
        // ListItem
        public List<Particle> particleList = new List<Particle>();
          
        /// <summary>
        /// This is a localized string resource. Localized string resources always look like this:
        /// <example>
        /// [Section.Name]
        /// </example>
        /// Localized resources must be present at least in the english language, as this is the default.
        /// In the english language file of this hello world plugin, you'll find the translation of this string.
        /// The language file is located at: /Language/strings_en.xml
        /// </summary>
        protected const string HELLOWORLD_RESOURCE = "[HelloWorld.HelloWorldText]";
        protected const string TranslateTransform0_X_RESOURCE = "20";
        protected const string TranslateTransform0_Y_RESOURCE = "20";
    
        /// <summary>
        /// Another localized string resource.
        /// </summary>
        protected const string COMMAND_TRIGGERED_RESOURCE = "[HelloWorld.ButtonTextCommandExecuted]";
    
        /// <summary>
        /// This property holds a string that we will modify in this tutorial.
        /// </summary>
        private readonly AbstractProperty _helloStringProperty;
        private readonly AbstractProperty _TranslateTransform0_XProperty;
        private readonly AbstractProperty _TranslateTransform0_YProperty;
    
        /// <summary>
        /// Constructor... this one is called by the WorkflowManager when this model is loaded due to a screen reference.
        /// </summary>
        public Model()
        {
          // In models, properties will always be WProperty instances. When using SProperties for screen databinding,
          // the system might run into memory leaks.
          _helloStringProperty = new WProperty(typeof(string), HELLOWORLD_RESOURCE);
          _TranslateTransform0_XProperty = new WProperty(typeof(string), TranslateTransform0_X_RESOURCE);
          _TranslateTransform0_YProperty = new WProperty(typeof(string), TranslateTransform0_Y_RESOURCE);
          //_ParticleHost = new WProperty(typeof(string), ParticleHost);
    
          Window_Loaded();
        }
          
        /// <summary>
        /// This sample property will be accessed by the hello_world screen. Note that the data type must be the same
        /// as in the instantiation of our backing property <see cref="_helloStringProperty"/>.
        /// </summary>
        public string HelloString
        {
          get { return (string) _helloStringProperty.GetValue(); }
          set { _helloStringProperty.SetValue(value); }
        }
    
        public string TranslateTransform0_X
        {
            get { return (string)_TranslateTransform0_XProperty.GetValue(); }
            set { _TranslateTransform0_XProperty.SetValue(value); }
        }
    
        public string TranslateTransform0_Y
        {
            get { return (string)_TranslateTransform0_YProperty.GetValue(); }
            set { _TranslateTransform0_YProperty.SetValue(value); }
        }
    
        /// <summary>
        /// This is the dependency property for our sample string. It is needed to propagate changes to the skin.
        /// </summary>
        /// <remarks>
        /// <para>
        /// If the screen databinds to the <see cref="HelloString"/> property in a binding mode which will propagate data
        /// changes from the model to the skin, the SkinEngine will attach a change handler to this property.
        /// </para>
        /// <para>
        /// In other words: Every property <c>Xyz</c>, which should be able to be attached to, must be present also as
        /// <c>XyzProperty</c>.
        /// Only if <c>XyzProperty</c> is present in the model, value changes can be propagated to the skin.
        /// </remarks>
        public AbstractProperty HelloStringProperty
        {
          get { return _helloStringProperty; }
        }
    
        public AbstractProperty TranslateTransform0_XProperty
        {
            get { return _TranslateTransform0_XProperty; }
        }
    
        public AbstractProperty TranslateTransform0_YProperty
        {
            get { return _TranslateTransform0_YProperty; }
        }
    
        /// <summary>
        /// Method which will be called from our screen. We will change the value of our HelloWorld string here.
        /// </summary>
        public void ChangeHelloWorldString()
        {
          HelloString = COMMAND_TRIGGERED_RESOURCE;
        }
    
        DispatcherTimer timer = new DispatcherTimer();
        Random random = new Random(DateTime.Now.Millisecond);
    
        // Some general values 
        double MaxSize = 30;
        double NumberOfParticles = 25;
        int Width = 800;
        int Height = 600;
        /*double VerticalVelocity = 0.4;
        double HorizontalVelocity = -2.2;
        double elapsed = 0.1;*/
          
        public void Window_Loaded()
        {
            for (int i = 0; i < NumberOfParticles; i++)
            {
                CreateParticle();
            }
    
            timer.Interval = TimeSpan.FromMilliseconds(33.33);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
    
            HelloString = "EXECUTED";
        }
          
        void timer_Tick(object sender, EventArgs e)
        {
            // I control "particle" from their ellipse representation 
            //foreach (Ellipse ellipse in ParticleHost.Children)
            //{
                /*var p = ellipse.Tag as Particle;
                var t = ellipse.RenderTransform as TranslateTransform;
    
                // Update location 
                t.X += p.Velocity.X;
                t.Y += p.Velocity.Y;
    
    
                // Check if the particle is too high 
                if (t.Y < -MaxSize)
                {
                    t.Y = Height + MaxSize;
                }
    
                // Check if the particle has gone outside 
                if (t.X < -MaxSize || t.X > Width + MaxSize)
                {
                    t.X = random.NextDouble() * Width;
                    t.Y = Height + MaxSize;
                }
    
                // Brush & Effect 
                //ellipse.Fill = p.Brush;
                ellipse.Fill = (Brush)Brushes.White.Clone();
                // Comment this line to deactivate the Blur Effect 
                ellipse.Effect = p.Blur;*/
            //}
    
            //----------------------------
    
            foreach (Particle particle in particleList)
            {
                TranslateTransform0_X = (ToDouble(TranslateTransform0_X) + particle.Velocity.X).ToString();
                TranslateTransform0_Y = (ToDouble(TranslateTransform0_Y) + particle.Velocity.Y).ToString();
    
                HelloString = "Transform X to " + TranslateTransform0_X;
    
                // Check if the particle is too high 
                if (ToDouble(TranslateTransform0_Y) < -MaxSize)
                {
                    TranslateTransform0_Y = (Height + MaxSize).ToString();
                }
    
                // Check if the particle has gone outside 
                if (ToDouble(TranslateTransform0_X) < -MaxSize || ToDouble(TranslateTransform0_X) > Width + MaxSize)
                {
                    TranslateTransform0_X = (random.NextDouble() * Width).ToString();
                    TranslateTransform0_Y = (Height + MaxSize).ToString();
                }
            }
        }
          
        private void CreateParticle()
        {
            
            
            // Brush (White) 
            var brush = System.Windows.Media.Brushes.White.Clone();
            // Opacity (0.2 <= 1) 
            brush.Opacity = 0.2 + random.NextDouble() * 0.8;
            // Blur effect 
            var blur = new BlurEffect();
            blur.RenderingBias = RenderingBias.Performance;
            // Radius (1 <= 40) 
            blur.Radius = 1 + random.NextDouble() * 39;
            // Ellipse 
            var ellipse = new Ellipse();
            // Size (from 15% to 95% of MaxSize) 
            ellipse.Width = ellipse.Height = MaxSize * 0.15 + random.NextDouble() * MaxSize * 0.8;
            // Starting location of the ellipse (anywhere in the scree
    
            // extraTags adden
            var p = new Particle();
    
            // Speed
            double speed = RandomWithVariance(20, 15);
            double velocityMultiplier = (random.NextDouble() + 0.25) * speed;
            double vX = (1.0 - (random.NextDouble() * 2.0)) * velocityMultiplier;
            // Only going from the bottom of the screen to the top (for now)
            double vY = -Math.Abs((1.0 - (random.NextDouble() * 2.0)) * velocityMultiplier);
    
            p.Velocity = p.Velocity = new Point(vX, vY);
            p.Blur = blur;
            ellipse.Tag = p;
            
    
            //this.ParticleHost.Children.Add(ellipse);
    
            TranslateTransform t;
    
            t = new TranslateTransform();
            ellipse.RenderTransform = t;
            ellipse.RenderTransformOrigin = new Point(0.5, 0.5);
            
            //t.X = RandomWithVariance(Width / 2, Width / 2);
            //t.Y = Height;
    
            //----------------------------------------
    
            // add particle to list
            particleList.Add(p);
    
            // set position
            TranslateTransform0_X = RandomWithVariance(Width / 2, Width / 2).ToString();
            TranslateTransform0_Y = Height.ToString();
        }
    
    
        private double RandomWithVariance(double midvalue, double variance)
        {
            double min = Math.Max(midvalue - (variance / 2), 0);
            double max = midvalue + (variance / 2);
            double value = min + ((max - min) * random.NextDouble());
            return value;
        }
    
          #region helper functions
    
        /// <summary>
        /// Wandelt in String in Double um
        /// </summary>
        /// <param name="In"></param>
        /// <returns></returns>
        public static double ToDouble(string In)
        {
            In = In.Replace(",", ".");
    
            return double.Parse(In, System.Globalization.CultureInfo.InvariantCulture);
        }
    
        /// <summary>
        /// Wandelt String in Double um mit Default falls es nicht möglich ist
        /// </summary>
        /// <param name="In"></param>
        /// <param name="Default"></param>
        /// <returns></returns>
        public static double ToDouble(string In, double Default)
        {
            double dblOut;
    
            In = In.Replace(",", ".");
    
            try
            {
                dblOut = double.Parse(In, System.Globalization.CultureInfo.InvariantCulture);
            }
            catch
            {
                dblOut = Default;
            }
    
            return dblOut;
        }
    
        /// <summary>
        /// Wandelt einen String in Double um (Default = 0 oder es wird eine Exception ausgelöst)
        /// </summary>
        /// <param name="In">String</param>
        /// <param name="UseExceptions">True (Exception wird ausgelöst) oder False (Default 0 wird verwendet)</param>
        /// <returns></returns>
        public static double ToDouble(string In, bool UseExceptions)
        {
            double dblOut;
    
            In = In.Replace(",", ".");
    
            try
            {
                dblOut = double.Parse(In, System.Globalization.CultureInfo.InvariantCulture);
            }
            catch (Exception ex)
            {
                if (UseExceptions)
                    throw ex;
                else
                    dblOut = 0;
            }
    
            return dblOut;
        }
    
          #endregion
      }
    }

    hello-world-actions-xml

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Hello world workflow state actions -->
    <Workflow DescriptorVersion="1.0">
      <MenuActions>
        <!-- This is the workflow action which will be shown in the main menu in the home screen.
             A PushNavigationTransition is a static action which is always visible in one or more defined
             workflow states. When executed, the given target state will be pushed onto the workflow navigation stack.
             There are also other action types which can be used at this place, for example it is possible to
             make the action visible and invisible programmatically when using a workflow contributor action.
    
             The action's name is only needed for debugging purposes and won't be shown to the user.
    
             The DisplayCategory is used to group actions together. There is no detailed definition which groups
             are present but the idea is that each plugin developer uses its own display categories to group its actions
             together. There are also some common display categories which can be reused here. Use the first letter
             as an indicator for the sort ordering, for example "z" for actions which should be posed at the end,
             "a" for the beginning, etc.
    
             The SortOrder is used for finer grained sorting inside a display category. We suggest to use a single, lower-case
             letter here.
    
             The SourceState attribute is needed to tell the system in which states the action should be visible.
             Use the state's id here. You can also use a star ("*"). In that case, the action will be shown in each
             state.
    
             The TargetState attribute must always contain an id of a valid target state where the sytem will navigate to
             when this action is executed.
    
             The DisplayTitle will be shown in the main menu for this action. -->
        <PushNavigationTransition Id="EA48BD6E-60D3-45b2-9C35-1AB437CC72FB"
            Name="Home->HelloWorld"
            DisplayCategory="z-HelloWorld"
            SortOrder="a"
            SourceState="7F702D9C-F2DD-42da-9ED8-0BA92F07787F"
            TargetState="D5CD9D35-1B36-4ede-8BED-A4FB658F27BD"
            DisplayTitle="[HelloWorld.MenuEntry]"/>
      </MenuActions>
    </Workflow>

    hallo-world-states.xml

    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Hello world workflow states -->
    <Workflow DescriptorVersion="1.0">
      <States>
        <!-- This is the workflow state which corresponds to the hello world screen. Each workflow state corresponds to
             a certain UI state. The id is needed to be able to reference the state, for example in the action which
             navigates to this state, see in file hello-world-actions.xml.
    
             The name of the state is only needed for debug reasons and will not be shown to the user.
    
             The MainScreen will automatically be shown by the workflow manager when switching to the state.
             It is also possible to set the screen programmatically when using a workflow model.
    
             The DisplayLabel is the string which is shown in the Navigation bar for this state. -->
        <WorkflowState Id="D5CD9D35-1B36-4ede-8BED-A4FB658F27BD"
            Name="HelloWorldMain" MainScreen="hello_world"
            DisplayLabel="[HelloWorld.StateDisplayLabel]"/> <!-- No workflow model -->
      </States>
    </Workflow>

    puuuhhh, a lot of stuff^^

    If I'm executing the source above I will get the error "Error loading skin resource.." (log attached)
    And in the log I find this line:
    System.ArgumentException: WorkflowManager: Model with id '5726da5a-70d5-458f-af67-611293d97912' is not available

    the id is the same as from the standard hallo world plugin... but the strange thing is if I change the first lines in the helloworld.xaml to this (removing the context="ID"):

    Code:
    <DockPanel Name="FastParticleBackground.Window1"
    xmlns="www.team-mediaportal.com/2008/mpf/directx"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    I can "open" my plugin, but I don't see the label and the ellipse doesn't move... but I think it should work...
    The question is now: What is the context="ID" for in the first lines?! Do I need it?

    I will try still more debugging an maybe I will get further information ;)
     

    Baboonanza

    Retired Team Member
  • Premium Supporter
  • February 5, 2010
    143
    57
    North London
    Home Country
    United Kingdom United Kingdom
    Removing the context ID bit simply prevents the xaml being linked to the model, so neturally you won't get the error message that it can't find it :)

    The root cause of the problem is this exception:
    Code:
    2010-11-20 15:30:22.911131 [Error][InputManager dispatch thread]: PluginManager: Error building plugin item '5726DA5A-70D5-458f-AF67-611293D97912' at location '/Models'
    Exception: System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.InvalidOperationException: Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies für viele Komponenten der Benutzeroberfläche erforderlich ist.
       bei System.Windows.Input.InputManager..ctor()
       bei System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
       bei System.Windows.Input.InputManager.get_Current()
       bei System.Windows.Input.KeyboardNavigation..ctor()
       bei System.Windows.FrameworkElement.FrameworkServices..ctor()
       bei System.Windows.FrameworkElement.EnsureFrameworkServices()
       bei System.Windows.FrameworkElement..ctor()
       bei System.Windows.Shapes.Ellipse..ctor()
       bei Models.HelloWorld.Model.CreateParticle()
       bei Models.HelloWorld.Model.Window_Loaded()
       bei Models.HelloWorld.Model..ctor()
       --- Ende der internen Ausnahmestapelüberwachung ---
       bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
       bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)
       bei System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
       bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
       bei System.Activator.CreateInstance(Type type)
       bei MediaPortal.Core.PluginManager.PluginRuntime.InstantiatePluginObject(String typeName) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\PluginManager\PluginRuntime.cs:Zeile 238.
       bei MediaPortal.Core.Services.PluginManager.Builders.InstanceBuilder.BuildItem(PluginItemMetadata itemData, PluginRuntime plugin) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\Services\PluginManager\Builders\InstanceBuilder.cs:Zeile 45.
       bei MediaPortal.Core.Services.PluginManager.PluginManager.RequestItem(PluginItemRegistration itemRegistration, Type type, IPluginItemStateTracker stateTracker) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\Services\PluginManager\PluginManager.cs:Zeile 409.
      Message: Ein Aufrufziel hat einen Ausnahmefehler verursacht.
      Site   : System.Object CreateInstance(System.RuntimeType, Boolean, Boolean, Boolean ByRef, System.RuntimeMethodHandle ByRef, Boolean ByRef)
      Source : mscorlib
    Inner Exception(s):
    Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies für viele Komponenten der Benutzeroberfläche erforderlich ist.
    Stack Trace:
       bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
       bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)
       bei System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
       bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
       bei System.Activator.CreateInstance(Type type)
       bei MediaPortal.Core.PluginManager.PluginRuntime.InstantiatePluginObject(String typeName) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\PluginManager\PluginRuntime.cs:Zeile 238.
       bei MediaPortal.Core.Services.PluginManager.Builders.InstanceBuilder.BuildItem(PluginItemMetadata itemData, PluginRuntime plugin) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\Services\PluginManager\Builders\InstanceBuilder.cs:Zeile 45.
       bei MediaPortal.Core.Services.PluginManager.PluginManager.RequestItem(PluginItemRegistration itemRegistration, Type type, IPluginItemStateTracker stateTracker) in M:\Programmieren\C#\MediaPortal 2\trunk - Kopie\MediaPortal\Source\System\MediaPortal.Core\Services\PluginManager\PluginManager.cs:Zeile 409.
    Since the exception is in German I can't understand it but basically the model has't been loaded, so when SkinEngine can't find it. I have seen the same problem when a model has a dependency (a 'using') on an assembly that can't be resolved at run-time, but I don't think that's the problem here.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    Hmm sorry, the error message doesn't say anything to me either and I can read German^^

    the translation:
    Ein Aufrufziel hat einen Ausnahmefehler verursacht.
    is
    Exception has been thrown by the target of an invocation.


    Beim aufrufenden Thread muss es sich um einen STA-Thread handeln, da dies für viele Komponenten der Benutzeroberfläche erforderlich ist.
    is
    The calling thread must be STA, because many UI components require this.

    Maybe you can tell me more now :)

    //Edit:
    Yes, I also thought that this exception is the reason for the problem, but I can't find the root of the exception...
    Another problem is that I can't debug with VS2010 because I don't have dokan installed and without dokan installed I get a break shortly after starting MP II^^

    //Edit2:
    I solved it by comment some unneeded stuff out...
    But thanks for your help ;)

    Sorry that I have so much questions, but is there something special about timers?!

    I have the following function:
    Code:
    public void Window_Loaded()
        {
            for (int i = 0; i < NumberOfParticles; i++)
            {
                CreateParticle();
            }
    
            timer.Interval = TimeSpan.FromMilliseconds(33.33);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
    
            logger.Info("HelloWorld: Window_Loaded() - timer started: " + timer.IsEnabled.ToString());
            HelloString = "EXECUTED";
        }
    In the log I can see the message:
    2010-11-20 18:47:19.118072 [Info.][InputManager dispatch thread]: HelloWorld: Window_Loaded() - timer started: True
    This mean the Timer should be active right?

    But the next message doesn't appear:

    Code:
    public void timer_Tick(object sender, EventArgs e)
        {
            logger.Info("HelloWorld: TimerTick");
    //... other stuff
    }

    But this time there is no exception in the logs xD

    All this is in the models.cs and I think the model is only under special circumstances active oO

    But the good news is that I'm getting closer and closer to understand all this stuff :p
     

    Albert

    MP2 Developer
  • Premium Supporter
  • February 18, 2008
    1,297
    1,130
    45
    Freiburg im Breisgau, Germany
    Home Country
    Germany Germany
    AW: Skinning contest: One month to go

    At first I tried to understand the ResourceWrapper, but I still don't get the point oO
    In the file ShowPlaylist.xaml you are using the following line (for example):

    Code:
    <ResourceWrapper x:Key="Contents_Element">

    I I don't find any reference in a .cs file to this "resource"... Also there is no reference in any .xaml file to "Contents_Element".
    See file master_menu.xaml#74:

    Code:
    <ContentPresenter Margin="10,0,10,10" x:Name="ContentViewer" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
        Content="{DynamicResource Contents_Element}"/>


    Code:
    <SomeUIElement>
      <Resources>
        <ResourceWrapper x:Key="BlackColor" Resource="#FF000000"/>
      </Resources>
    </SomeUIElement>
    
    <label color="BlackColor" content="string" />
    To make that work, in your "label", you need to write "{StaticResource BlackColor}" or "{ThemeResource BlackColor}".


    Code:
    public void Window_Loaded()
        {
            for (int i = 0; i < NumberOfParticles; i++)
            {
                CreateParticle();
            }
    
            timer.Interval = TimeSpan.FromMilliseconds(33.33);
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
    
            logger.Info("HelloWorld: Window_Loaded() - timer started: " + timer.IsEnabled.ToString());
            HelloString = "EXECUTED";
        }
    I hope that is a test program and not code which you wrote into the SkinEngine!?

    If it is a test program; there are multiple timer classes, is it possible that your timer class depends on the windows message loop but you maybe blocked it?
     

    Users who are viewing this thread

    Top Bottom