/// <summary>Clears all content from the UI and all WorldUI's. /// Please note that it is safer to set innerHTML to a blank string for a particular UI than calling this.</summary> public static void ClearAll() { content = null; if (Renderer != null) { Renderer.Destroy(); Renderer = null; document = null; } Fonts.Clear(); AtlasStacks.Clear(); Http.Clear(); SPA.Clear(); UIAnimation.Clear(); DynamicTexture.RemoveAll(); PowerUI.Input.Clear(); ScreenInfo.Clear(); WorldUI currentWorldUI = FirstWorldUI; while (currentWorldUI != null) { currentWorldUI.Destroy(); currentWorldUI = currentWorldUI.UIAfter; } LastWorldUI = null; FirstWorldUI = null; }
/// <summary>Clears and entirely destroys the UI and WorldUI's. Calling this is not a requirement and can only be reversed by calling Start again.</summary> public static void Destroy() { ClearAll(); if (GUINode != null) { GameObject.Destroy(GUINode); GUINode = null; GUICamera = null; CameraNode = null; CameraTransform = null; } if (GlobalUpdater != null) { GameObject.Destroy(GlobalUpdater); GlobalUpdater = null; } _Started = false; Variables = null; LastWorldUI = null; FirstWorldUI = null; // Clear batch pool: UIBatchPool.Clear(); }
/// <summary>Called when this audio is expected to start. Note that context may be null.</summary> public virtual void Start(Dom.Node context) { // Play the clip in the context's doc: WorldUI wUI = (context.document as HtmlDocument).worldUI; GameObject root; if (wUI == null) { root = UI.GUINode; } else { root = wUI.gameObject; } GameObject host = new GameObject(); host.transform.parent = root.transform; Source = host.AddComponent <AudioSource>(); // 3D space if worldUI; 2D space if main UI: Source.spatialBlend = (wUI == null) ? 0f : 1f; Source.clip = Clip; Source.Play(); }
/// <summary>Clears all content from the UI and all WorldUI's. /// Please note that it is safer to set innerHTML to a blank string for a particular UI than calling this.</summary> public static void ClearAll() { content = null; if (Renderer != null) { Renderer.Destroy(); Renderer = null; document = null; } Fonts.Clear(); AtlasStacks.Clear(); Web.Clear(); Spa.SPA.Clear(); UIAnimation.Clear(); ScreenInfo.Clear(); WorldUI currentWorldUI = FirstWorldUI; while (currentWorldUI != null) { currentWorldUI.Destroy(); currentWorldUI = currentWorldUI.UIAfter; } LastWorldUI = null; FirstWorldUI = null; }
/// <summary>Called by Dom when the language of the UI changes. /// This changes the language of all on screen &variables;. /// <see cref="UI.Language"/>.</summary> /// <param name="code">The language code/id (e.g. en).</param> public static void OnLanguageChange(string code) { // Get the new language: LanguageInfo language = LanguageInfo.Get(code); if (language == null) { // This happens when the localisation system isn't in use at all yet. // There's no point going any further. return; } bool goesLeftwards = language.leftwards; // For the main UI: LanguageChanged(goesLeftwards, document); // And all in-world UI's: WorldUI worldUI = FirstWorldUI; while (worldUI != null) { LanguageChanged(goesLeftwards, worldUI.document); worldUI = worldUI.UIAfter; } // Re-resolve any already applied UI elements: ResolveAllVariables(); }
/// <summary>Gets a document by its unique ID.</summary> public static Document GetByUniqueID(uint uniqueID) { // First, search UI.document: Document result = SearchForID(UI.document, uniqueID); if (result != null) { return(result); } // Search every WorldUI: WorldUI current = UI.LastWorldUI; while (current != null) { // Search it too: result = SearchForID(current.document, uniqueID); if (result != null) { return(result); } current = current.UIBefore; } return(null); }
/// <summary>Creates a new World UI with the given pixels of space and a given name. /// The gameobjects origin sits at the middle of the UI by default. See <see cref="PowerUI.WorldUI.SetOrigin"/>. /// By default, 100 pixels are 1 world unit. See <see cref="PowerUI.WorldUI.SetResolution"/>.</summary> /// <param name="name">The name for the UI's gameobject.</param> /// <param name="widthPX">The width in pixels of this UI.</param> /// <param name="heightPX">The height in pixels of this UI.</param> public WorldUI(string name, int widthPX, int heightPX) { // Start the UI: UI.Start(); // Create the gameobject: gameObject = new GameObject(); gameObject.name = name; // Grab the name: Name = name; transform = gameObject.transform; Renderer = new Renderman(this); SetDepthResolution(1f); // Apply the default scale: transform.localScale = new Vector3(1 / 100f, 1 / 100f, 1 / 100f); document = Renderer.RootDocument as HtmlDocument; // Add it to the UI update linked list: if (UI.FirstWorldUI == null) { UI.FirstWorldUI = UI.LastWorldUI = this; } else { UIBefore = UI.LastWorldUI; UI.LastWorldUI = UI.LastWorldUI.UIAfter = this; } SetDimensions(widthPX, heightPX); }
/// <summary>Collects all available documents from the main UI and any WorldUI's.</summary> public static List <DocumentEntry> GetDocuments(bool refresh) { if (AllDocuments_ != null && !refresh) { return(AllDocuments_); } List <DocumentEntry> results = new List <DocumentEntry>(); AllDocuments_ = results; // First, search UI.document: Search(UI.document, "Main UI", results); // Search every WorldUI: WorldUI current = UI.LastWorldUI; while (current != null) { // Search it too: Search(current.document, current.Name, results); current = current.UIBefore; } // Cache names: AllDocumentNames_ = new string[results.Count]; for (int i = 0; i < results.Count; i++) { results[i].Index = i; string name = results[i].Name; if (string.IsNullOrEmpty(name)) { // Using doc.location: Dom.Location loc = results[i].Document.location; if (loc == null) { name = "about:blank"; } else { name = loc.absolute; } } name = ListableName(name); // Set into names: AllDocumentNames_[i] = name; } return(results); }
/// <summary>Updates all worldUI's. Called internally to update pixel perfect WorldUI's.</summary> public static void UpdateAll() { if (UI.FirstWorldUI != null) { WorldUI current = UI.FirstWorldUI; while (current != null) { current.Update(); current = current.UIAfter; } } }
/// <summary>Finds and sets OnWorldUI from the given transform. /// If successful, Success will be true.</summary> /// <returns>True if successful, false otherwise.</returns> public bool FindWorldUI(Transform transform) { if (WorldUI.PhysicsLookup == null) { OnWorldUI = null; Successful = false; } else { Successful = WorldUI.PhysicsLookup.TryGetValue(transform, out OnWorldUI); } return(Successful); }
/// <summary>Fires an event into the scene of the camera.</summary> internal void FireIntoScene(UIEvent e) { if (e == null) { return; } // Get coords relative to the element. These are non-standard convenience properties: float localX = e.localX; float localY = e.localY; // Flip Y because Unity is upside down relative to input coords: localY = ScreenInfo.ScreenY - 1 - localY; // Fire off an input event at that point: RaycastHit worldUIHit; if (Physics.Raycast(Camera.ScreenPointToRay(new Vector2(localX, localY)), out worldUIHit)) { // Did it hit a worldUI? WorldUI worldUI = WorldUI.Find(worldUIHit); if (worldUI == null) { // Nope! return; } // Resolve the hit into a -0.5 to +0.5 point: float x; float y; worldUI.ResolvePoint(worldUIHit, out x, out y); // Map it from a relative point to a 'real' one: Vector2 point = worldUI.RelativePoint(x, y); // Apply to x/y: x = point.x; y = point.y; // Pull an element from that worldUI: Element el = worldUI.document.elementFromPointOnScreen(x, y); if (el != null) { // Fire the event for that element: el.dispatchEvent(e); } } }
/// <summary>Resolves all &variables; as used by PowerUI to their new values. Used when e.g. the language changes.</summary> private static void ResolveAllVariables() { // Re-resolve all current variables. // First, the main UI: ResolveAllVariables(document); // And all WorldUI's: WorldUI worldUI = FirstWorldUI; while (worldUI != null) { ResolveAllVariables(worldUI.document); worldUI = worldUI.UIAfter; } }
/// <summary>Finds a WorldUI by name. Note that this is a linear scan so it's very wise to keep hold of references to your WorldUI's where possible. /// If multiple WorldUI's have the same name, the latest one created is returned.</summary> /// <param name="name">The WorldUI's name.</param> /// <returns>The latest WorldUI with this name, or null if not found.</returns> public static WorldUI Find(string name) { // This function seeks "backwards" to find the latest one. WorldUI current = UI.LastWorldUI; while (current != null) { if (current.Name == name) { return(current); } current = current.UIBefore; } return(null); }
/// <summary>Requests all UI's to update. This occurs when an atlas has been optimised.</summary> public static void RequestFullLayout() { // Request renderer layout (full): Renderer.RequestLayout(); WorldUI current = FirstWorldUI; while (current != null) { if (current.Renderer != null) { // Request worldUI layout (full): current.Renderer.RequestLayout(); } current = current.UIAfter; } }
public static void OnVariableChange(string code) { if (code == "*") { ResolveAllVariables(); } else { // The main UI: ResolveVariable(document, code); // And all WorldUI's: WorldUI worldUI = FirstWorldUI; while (worldUI != null) { ResolveVariable(worldUI.document, code); worldUI = worldUI.UIAfter; } } }
/// <summary>Checks if the given hit was on a WorldUI. If it was, it returns the WorldUI that was hit.</summary> public static WorldUI Find(RaycastHit hit) { Transform transform = hit.transform; if (transform == null) { return(null); } // Try the transform or it's parent: WorldUI found = Find(transform); if (found == null && transform.parent != null) { // Try the parent instead: found = Find(transform.parent); } // Found is now just our result: return(found); }
/// <summary>Makes sure the default text direction matches the one given by the language (e.g. Arabic may tell PowerUI it goes leftwards). /// Applies to the main UI and all in-world UI's.</summary> private static void UpdateTextDirection() { LanguageSet language = (LanguageSet)(GetLanguageLoader().Get(Language)); if (language == null) { return; } bool goesLeftwards = language.GoesLeftwards; // For the main UI: UpdateTextDirection(goesLeftwards, document); // And all in-world UI's: WorldUI worldUI = FirstWorldUI; while (worldUI != null) { UpdateTextDirection(goesLeftwards, worldUI.document); worldUI = worldUI.UIAfter; } }
/// <summary>Finds and sets OnWorldUI from the given transform. /// If successful, Success will be true.</summary> /// <returns>True if successful, false otherwise.</returns> public bool FindWorldUI(Transform transform){ if(WorldUI.PhysicsLookup==null){ OnWorldUI=null; Successful=false; }else{ Successful=WorldUI.PhysicsLookup.TryGetValue(transform,out OnWorldUI); } return Successful; }
/// <summary>Creates a new World UI with the given pixels of space and a given name. /// The gameobjects origin sits at the middle of the UI by default. See <see cref="PowerUI.WorldUI.SetOrigin"/>. /// By default, 100 pixels are 1 world unit. See <see cref="PowerUI.WorldUI.SetResolution"/>.</summary> /// <param name="name">The name for the UI's gameobject.</param> /// <param name="widthPX">The width in pixels of this UI.</param> /// <param name="heightPX">The height in pixels of this UI.</param> public WorldUI(string name,int widthPX,int heightPX){ // Start the UI: UI.Start(); // Create the gameobject: gameObject=new GameObject(); gameObject.name=name; // Grab the name: Name=name; transform=gameObject.transform; Renderer=new Renderman(this); SetDepthResolution(0.01f); // Apply the default scale: transform.localScale=new Vector3(1/100f,1/100f,1f); document=Renderer.RootDocument; // Add it to the UI update linked list: if(UI.FirstWorldUI==null){ UI.FirstWorldUI=UI.LastWorldUI=this; }else{ UIBefore=UI.LastWorldUI; UI.LastWorldUI=UI.LastWorldUI.UIAfter=this; } SetDimensions(widthPX,heightPX); SetInputMode(PowerUI.Input.WorldInputMode); }
/// <summary>Clears all content from the UI and all WorldUI's. /// Please note that it is safer to set innerHTML to a blank string for a particular UI than calling this.</summary> public static void ClearAll(){ content=null; if(Renderer!=null){ Renderer.Destroy(); Renderer=null; document=null; } Fonts.Clear(); AtlasStacks.Clear(); Http.Clear(); SPA.Clear(); UIAnimation.Clear(); DynamicTexture.RemoveAll(); PowerUI.Input.Clear(); ScreenInfo.Clear(); WorldUI currentWorldUI=FirstWorldUI; while(currentWorldUI!=null){ currentWorldUI.Destroy(); currentWorldUI=currentWorldUI.UIAfter; } LastWorldUI=null; FirstWorldUI=null; }
/// <summary>Clears and entirely destroys the UI and WorldUI's. Calling this is not a requirement and can only be reversed by calling Start again.</summary> public static void Destroy(){ ClearAll(); if(GUINode!=null){ GameObject.Destroy(GUINode); GUINode=null; GUICamera=null; CameraNode=null; CameraTransform=null; } if(GlobalUpdater!=null){ GameObject.Destroy(GlobalUpdater); GlobalUpdater=null; } Started=false; Variables=null; LastWorldUI=null; FirstWorldUI=null; // Clear batch pool: UIBatchPool.Clear(); }
/// <summary>Finds an EventTarget from the given screen location. /// This fires a ray into the scene if the point isn't on the main UI and caches the hit in the given pointer. /// X and Y are updated with the document-relative point if it's on a WorldUI/ on the Unity UI.</summary> public static EventTarget TargetFromPoint(ref float x,ref float y,InputPointer pointer){ Element result=null; if(UI.document!=null){ // Test the main UI: result=UI.document.elementFromPointOnScreen(x,y); if(result!=null){ // Is it transparent or not html/body? if(AcceptsInput(result)){ // Great, we're done! if(pointer!=null){ pointer.LatestHitSuccess=false; } return result; } } } // Handle a Unity UI if needed. Vector2 point; #if HANDLE_UNITY_UI if(UnityUICaster!=null){ // Try hitting the Unity UI first. point=new Vector2(x,ScreenInfo.ScreenY-1-y); HtmlDocument panelDoc=MapToUIPanel(ref point); if(panelDoc!=null){ // Test for an element there: result=panelDoc.elementFromPointOnScreen(point.x,point.y); if(result!=null){ // Is it transparent? // We're still checking a UI so we might still pass "through" it. if(AcceptsInput(result)){ // Got a hit! Update x/y: x=point.x; y=point.y; if(pointer!=null){ pointer.LatestHitSuccess=false; } return result; } } } } #endif // Go after WorldUI's next. RaycastHit worldUIHit; Camera cam=CameraFor3DInput; if(cam==null){ // No camera! if(pointer!=null){ pointer.LatestHitSuccess=false; } return null; } Vector2 screenPoint = new Vector2(x,ScreenInfo.ScreenY-1-y); if(pointer == null){ // Cast into the scene now: Ray ray=cam.ScreenPointToRay(screenPoint); if(!Physics.Raycast(ray,out worldUIHit)){ // Nothing hit. return null; } }else if(!pointer.Raycast(out worldUIHit,cam,screenPoint)){ // Nothing hit. pointer.LatestHitSuccess=false; return null; } // Cache it: if(pointer!=null){ pointer.LatestHit=worldUIHit; pointer.LatestHitSuccess=true; } // Did it hit a worldUI? WorldUI worldUI=WorldUI.Find(worldUIHit); if(worldUI==null){ // Nope! Get the eventTarget for the gameObject: #if Enable3DInput return worldUIHit.transform.gameObject.getEventTarget(); #else return null; #endif } // Resolve the hit into a -0.5 to +0.5 point: // (we're ok to reuse x/y here): worldUI.ResolvePoint(worldUIHit,out x,out y); // Map it from a relative point to a 'real' one: point=worldUI.RelativePoint(x,y); // Apply to x/y: x=point.x; y=point.y; // Pull an element from that worldUI: return worldUI.document.elementFromPointOnScreen(x,y); }
public override void OnEnable() { // Dump renderer/filter: MeshRenderer mr = gameObject.GetComponent <MeshRenderer>(); // True if we've got the visual guide: bool hasGuide = false; if (mr != null && mr.material != null && mr.material.name.StartsWith("worldUIMaterial")) { // Remove it: GameObject.Destroy(mr); hasGuide = true; // Remove filter too: MeshFilter filter = gameObject.GetComponent <MeshFilter>(); if (filter != null) { GameObject.Destroy(filter); } } // First, figure out the 'aspect ratio' of the scale: Vector3 scale = transform.localScale; transform.localScale = Vector3.one * customWidthInMeter; float yAspect = scale.z / scale.x; if (customRatio > 0) { yAspect = customRatio; } // Calc the number of pixels: int height = (int)((float)PixelWidth * yAspect); // Generate a new UI (the name is optional). // The two numbers are the dimensions of our virtual screen: WorldUI = new WorldUI(gameObject.name, PixelWidth, height); // Settings: WorldUI.PixelPerfect = PixelPerfect; WorldUI.AlwaysFaceCamera = AlwaysFaceTheCamera; if (Expiry != 0f) { WorldUI.SetExpiry(Expiry); } // Give it some content using PowerUI.Manager's Navigate method: // (Just so we can use the same Html/ Url fields - it's completely optional) Navigate(WorldUI.document); // Parent it to the GO: WorldUI.ParentToOrigin(transform); if (hasGuide) { // Rotate it 90 degrees about x (to match up with the guide): WorldUI.transform.localRotation = Quaternion.AngleAxis(90f, new Vector3(1f, 0f, 0f)); } // Set the scale such that the width "fits". // The panel will be PixelWidth wide, so we want to divide by that to get to '1'. // Note that the 10 is because a plane is 10 units wide. // We then multiply it by whatever scale (on x) the user originally wanted. // The y scale is accounted for by the computed pixel height (we don't want to distort it). float scaleFactor = (10f * scale.x) / (float)PixelWidth; WorldUI.transform.localScale = new Vector3(scaleFactor, scaleFactor, scale.y); // Optionally accept input: WorldUI.AcceptInput = InputEnabled; }
/// <summary>Resolves the given target to a document.</summary> /// <returns>The targeted document. Null if there is no document at all and the target is essentially outside of Unity.</returns> public HtmlDocument ResolveTarget(string target) { // Grab the document the element is in: HtmlDocument document = htmlDocument; if (target == null) { // No target - does the document define a default one? // Note that this is set with the "base" html tag. if (document.location != null) { target = document.baseTarget; } } // Null target is the same as _self. if (string.IsNullOrEmpty(target)) { target = "_self"; } // Grab the window: Window window = document.window; switch (target) { case "_blank": // Open the given url outside Unity. return(null); case "_top": // Open the given URL at the top window. return(window.top.document); case "_parent": // Open it there: return(window.parent.document); case "_self": // Open it in this document: return(document); case "_main": // Open into the main UI: return(UI.document); default: // Anything else and it's the name of an iframe (preferred) or a WorldUI. // Get the element by name: HtmlElement iframeElement = document.getElementByAttribute("name", target) as HtmlElement; if (iframeElement == null) { // WorldUI with this name? WorldUI ui = WorldUI.Find(target); if (ui == null) { // Not found - same as self: return(document); } // Load into the WorldUI: return(ui.document); } // Great, we have an iframe - grab the content document: return(iframeElement.contentDocument); } }
public override void OnEnable() { // Watch for any file changes: Watch(); // Dump renderer/filter, unless it's flat: MeshRenderer mr = gameObject.GetComponent <MeshRenderer>(); // True if we've got the visual guide: bool hasGuide = false; if (!MakeItFlat && mr != null && mr.material != null && mr.material.name.StartsWith("worldUIMaterial")) { // Remove it: GameObject.Destroy(mr); hasGuide = true; // Remove filter too: MeshFilter filter = gameObject.GetComponent <MeshFilter>(); if (filter != null) { GameObject.Destroy(filter); } } // First, figure out the 'aspect ratio' of the scale: Vector3 scale = transform.localScale; float yAspect = scale.z / scale.x; // Calc the number of pixels: int height = (int)((float)PixelWidth * yAspect); if (MakeItFlat) { // Create it as a FlatWorldUI instead: FlatWorldUI fwUI = new FlatWorldUI(PixelWidth, height); WorldUI = fwUI; // Grab the texture and apply it to the material: if (mr != null) { Material mat = new Material(mr.material.shader); mat.mainTexture = fwUI.texture; mr.material = mat; // The flat version is upside down relative to the 3D one: mat.mainTextureScale = new Vector2(-1f, -1f); mat.mainTextureOffset = new Vector2(1f, 1f); } // Give it some content using PowerUI.Manager's Navigate method: // (Just so we can use the same Html/ Url fields - it's completely optional) Navigate(WorldUI.document); if (InputEnabled) { // Create a box collider: BoxCollider bc = gameObject.AddComponent <BoxCollider>(); // Accept input from it: fwUI.AcceptInputFrom(bc); } } else { // Reset local scale: // transform.localScale=Vector3.one; // Generate a new UI (the name is optional). // The two numbers are the dimensions of our virtual screen: WorldUI = new WorldUI(gameObject.name, PixelWidth, height); // Settings: WorldUI.PixelPerfect = PixelPerfect; WorldUI.AlwaysFaceCamera = AlwaysFaceTheCamera; if (Expiry != 0f) { WorldUI.SetExpiry(Expiry); } // Give it some content using PowerUI.Manager's Navigate method: // (Just so we can use the same Html/ Url fields - it's completely optional) Navigate(WorldUI.document); // Parent it to the GO: WorldUI.ParentToOrigin(transform); if (hasGuide) { // Rotate it 90 degrees about x (to match up with the guide): // WorldUI.transform.localRotation=Quaternion.AngleAxis(90f,new Vector3(1f,0f,0f)); } // Set the scale such that the width "fits". // The panel will be PixelWidth wide, so we want to divide by that to get to '1'. // Note that the 10 is because a plane is 10 units wide. // We then multiply it by whatever scale (on x) the user originally wanted. // The y scale is accounted for by the computed pixel height (we don't want to distort it). float scaleFactor = (10f * scale.x) / (float)PixelWidth; WorldUI.transform.localScale = new Vector3(scaleFactor, scaleFactor, scaleFactor); // Optionally accept input: WorldUI.AcceptInput = InputEnabled; } // Input is always inverted for these: WorldUI.InvertResolve = true; }
/// <summary>Updates the UI. Don't call this - PowerUI knows when it's needed; This is done from Start and WorldUI constructors.</summary> public static void InternalUpdate() { // Update any callbacks: if (Callbacks.FirstToRun != null) { Callbacks.RunAll(); } // Update animations: SPA.Update(); // Update any Http requests: Http.Update(); if (WorldUI.LiveUpdatablesAvailable) { WorldUI.UpdateAll(); } RedrawTimer += Time.deltaTime; if (RedrawTimer < RedrawRate) { return; } RedrawTimer = 0f; if (GUICamera == null) { return; } // Atlases: AtlasStacks.Update(); // Screen size: ScreenInfo.Update(); // Update Input (mouse/keys etc). PowerUI.Input.Update(); // Animations: UIAnimation.Update(); // Dynamic graphics: DynamicTexture.Update(); // Redraw the root html document (if it needs to be redrawn): Renderer.Update(); if (MainCameraPool != null && MainCameraPool.DidLayout) { // The main UI did a layout and we have a camera pool. // We now need to do some post-layout spring cleaning. MainCameraPool.ClearPool(); } // Redraw any in-world documents (if they need it). // Did we call update all above? bool worldUIRequiresUpdate = !WorldUI.LiveUpdatablesAvailable; // Clear the flag: WorldUI.LiveUpdatablesAvailable = false; if (FirstWorldUI != null) { WorldUI current = FirstWorldUI; while (current != null) { if (worldUIRequiresUpdate) { // Update: current.Update(); // Was it destroyed? if (current.Renderer == null) { // Hop to the next one: current = current.UIAfter; continue; } } if (current.Expires) { current.ExpiresIn -= RedrawRate; if (current.ExpiresIn <= 0f) { // Expire it: current.Expire(); // Hop to the next one: current = current.UIAfter; continue; } } // Update the renderer: current.Renderer.Update(); // Update the flag: if (current.PixelPerfect || current.AlwaysFaceCamera) { // We have at least one which is updateable: WorldUI.LiveUpdatablesAvailable = true; } current = current.UIAfter; } } // Flush any atlases: AtlasStacks.Flush(); }
/// <summary>Updates the UI. Don't call this - PowerUI knows when it's needed; This is done from Start and WorldUI constructors.</summary> public static void InternalUpdate() { // Get a deltaTime unaffected by timeScale: float deltaTime = Time.unscaledDeltaTime; RedrawTimer += deltaTime; // Update any callbacks: if (Callbacks.FirstToRun != null) { Callbacks.RunAll(); } // OnUpdate queue too: if (OnUpdate.FirstElement != null) { OnUpdate.Update(); } // Update animations: Spa.SPA.Update(deltaTime); if (WorldUI.LiveUpdatablesAvailable) { WorldUI.UpdateAll(); } if (RedrawTimer < RedrawRate) { return; } // Currently, RedrawTimer is exactly the amount of time we took: float frameTime = RedrawTimer; RedrawTimer = 0f; if (GUICamera == null) { return; } // Check for timeouts: Web.Update(frameTime); // Atlases: AtlasStacks.Update(); // Screen size: ScreenInfo.Update(); // Update Input (mouse/keys etc). PowerUI.Input.Update(); // Animations: UIAnimation.Update(frameTime); // Dynamic graphics: DynamicTexture.Update(); // Redraw the root html document (if it needs to be redrawn): Renderer.Update(); // Redraw any in-world documents (if they need it). // Did we call update all above? bool worldUIRequiresUpdate = !WorldUI.LiveUpdatablesAvailable; // Clear the flag: WorldUI.LiveUpdatablesAvailable = false; if (FirstWorldUI != null) { WorldUI current = FirstWorldUI; while (current != null) { if (worldUIRequiresUpdate) { // Update: current.Update(); // Was it destroyed? if (current.Renderer == null) { // Hop to the next one: current = current.UIAfter; continue; } } if (current.Expires) { current.ExpiresIn -= frameTime; if (current.ExpiresIn <= 0f) { // Expire it: current.Expire(); // Hop to the next one: current = current.UIAfter; continue; } } // Update the renderer: current.Renderer.Update(); // Update the flag: if (current.PixelPerfect || current.AlwaysFaceCamera) { // We have at least one which is updateable: WorldUI.LiveUpdatablesAvailable = true; } current = current.UIAfter; } } // Draw characters: Blaze.TextureCameras.Update(frameTime); // Flush any atlases: AtlasStacks.Flush(); }
/// <summary>Creates a new renderer for rendering in the world.</summary> public Renderman(WorldUI worldUI):this(){ Node=worldUI.gameObject; InWorldUI=worldUI; }