/// <summary>Creates a new element for the given document and as a child of the given parent.</summary> /// <param name="document">The document that this element will belong to.</param> /// <param name="parent">The element that this element will be parented to.</param> public Element(Document document,Element parent){ Document=document; ParentNode=parent; Style=new ElementStyle(this); }
/// <summary>Creates a new UIAnimation for animating CSS and immediately animates it. /// See <see cref="PowerUI.Element.animate"/>.</summary> /// <param name="animating">The element being animated.</param> /// <param name="properties">The CSS property string. Each property should define the value it will be when the animation is done.</param> /// <param name="constantSpeedTime">How long this animation lasts for at a constant speed.</param> /// <param name="timeToAccelerateFor">How long this animation accelerates for. Creates smooth animations when used.</param> /// <param name="timeToDecelerateFor">How long this animation decelerates for. Creates smooth animations when used.</param> public UIAnimation(Element animating,string properties,float constantSpeedTime,float timeToAccelerateFor,float timeToDecelerateFor){ Animating=animating; ElementStyle=Animating.Style; if(string.IsNullOrEmpty(properties)){ Wrench.Log.Add("No properties given to animate!"); return; } if(constantSpeedTime<0f){ constantSpeedTime=0f; } if(timeToAccelerateFor<0f){ timeToAccelerateFor=0f; } if(timeToDecelerateFor<0f){ timeToDecelerateFor=0f; } TotalTime=(timeToDecelerateFor + timeToAccelerateFor + constantSpeedTime); ConstantSpeedTime=constantSpeedTime; TimeToAccelerateFor=timeToAccelerateFor; TimeToDecelerateFor=timeToDecelerateFor; if(TotalTime==0f){ // Instant - probably a fault somewhere in the users request, so we won't do anything. Wrench.Log.Add("Instant css animation request ignored. Told to take no time to transition."); return; } if(timeToDecelerateFor==0f){ Decelerate=false; }else{ Decelerate=true; DecelerateAt=timeToAccelerateFor + constantSpeedTime; } if( properties.StartsWith(".") || properties.StartsWith("#") ){ // Targeting a selector, e.g. #fadedBox // First, get the selector style: Css.SelectorStyle selector=animating.Document.getStyleBySelector(properties); if(selector==null){ return; } // Animate each property: foreach(KeyValuePair<CssProperty,Css.Value> kvp in selector.Properties){ // Is it a composite property? Css.Value value=kvp.Value; // Grab the type: Css.ValueType type=value.Type; if(type==Css.ValueType.Null || type==Css.ValueType.Text){ // Can't deal with either of these. continue; } if(type==Css.ValueType.Rectangle || type==Css.ValueType.Point || type==Css.ValueType.Color){ // Animate it (note that we don't need to copy it): AnimateComposite(kvp.Key,value); }else{ // Animate it (note that we don't need to copy it): Animate(kvp.Key,-1,value,true); } } return; } string[] propertySet=properties.Split(';'); foreach(string currentProperty in propertySet){ if(currentProperty==""){ continue; } string[] keyValue=currentProperty.Split(Css.Style.Delimiter,2); if(keyValue.Length!=2){ continue; } string key=keyValue[0].Trim(); if(key=="opacity"){ key="color-overlay-a"; } // Grab the inner index: int innerIndex=Css.Value.GetInnerIndex(ref key); // Get the property: CssProperty property=CssProperties.Get(key); if(property==null){ Wrench.Log.Add("Warning: CSS property '"+keyValue[0]+"' not found during animate."); continue; } // Trim shouldn't be applied to inner-text's value, but we can't animate that anyway! This is all we need to do: string value=keyValue[1].Trim(); // Key could be a composite property - for example padding, which needs to be broken down into it's individual inner elements (e.g. padding-left) Css.ValueType type; if(innerIndex==-1){ type=Css.Value.TypeOf(property,ref value); }else{ type=Css.Value.TypeOf(value); } if(type==Css.ValueType.Null || type==Css.ValueType.Text){ // Can't deal with either of these. continue; }else if(type==Css.ValueType.Rectangle || type==Css.ValueType.Point || type==Css.ValueType.Color){ // We have a composite property (and we're animating the whole thing). Css.Value tempValue=new Css.Value(); tempValue.Set(value,type); // Animate it: AnimateComposite(property,tempValue); }else{ Animate(property,innerIndex,new Css.Value(value,type),true); } } }
/// <summary>Update causes all changes to be applied and layouts to occur.</summary> public void Update(){ if(DoLayout){ // Layout RootDocument. Layout(); }else if(StylesToPaint!=null){ // Repaint - these events fire from changes to things like colour/z-index etc; // Things which don't affect the position. // It's done down here incase a layout request is made. // If a layout request was made, it would overwrite any paint efforts made making them a waste of time. Css.ElementStyle style=StylesToPaint; StylesToPaint=null; while(style!=null){ style.IsPainting=false; style.Computed.Repaint(); style=style.Next; } // Flush all batches: UIBatch toFlush=FirstBatch; while(toFlush!=null){ toFlush.Flush(); toFlush=toFlush.BatchAfter; } } }
/// <summary>Relocates all DOM elements by calculating their onscreen position. /// Each element may allocate sections of the 3D mesh (blocks) which are then flushed out /// into the unity mesh and onto the screen.</summary> public void Layout(){ DoLayout=false; Reset(); // First, push all batches to the pool - inlined for speed: // Note that no isolated batches enter either the queue or the pool until their no longer isolated. if(FirstBatch!=null){ LastBatch.BatchAfter=UIBatchPool.First; UIBatchPool.First=FirstBatch; } FirstBatch=LastBatch=null; // Note: Batches are Prepared For Layout as they are added. LayoutOccuring=true; // Position elements locally. // This sets their ParentOffset values and as a result finds their PixelWidth. RootDocument.html.PositionLocally(); if(Input.Focused!=null){ Input.Focused.Handler.OnRenderPass(); // Make sure it didn't schedule anything. if(StylesToPaint!=null){ Css.ElementStyle style=StylesToPaint; StylesToPaint=null; while(style!=null){ style.IsPainting=false; style=style.Next; } } DoLayout=false; } // Next up, position them globally: // This calculates OffsetLeft/Top and also fires the render event on the computed style object. RootDocument.html.PositionGlobally(null); LayoutOccuring=false; // Tell each batch we're done laying them out: UIBatch currentBatch=FirstBatch; while(currentBatch!=null){ currentBatch.CompletedLayout(); currentBatch=currentBatch.BatchAfter; } if(StylesToPaint!=null){ // Clear the isPainting flag. Css.ElementStyle style=StylesToPaint; StylesToPaint=null; while(style!=null){ style.IsPainting=false; style=style.Next; } } // Hide all pool entries: UIBatchPool.HideAll(); }
/// <summary>Asks the renderer to perform a paint on the given style object next update.</summary> /// <param name="style">The style to paint.</param> public void RequestPaint(Css.ElementStyle style){ if(DoLayout||style.IsPainting){ return; } style.IsPainting=true; if(StylesToPaint==null){ StylesToPaint=style; style.Next=null; }else{ style.Next=StylesToPaint; StylesToPaint=style; } }