/// <summary>Creates a new canvas context for the given canvas element.</summary> /// <param name="canvas">The canvas for a particular canvas element.</param> public CanvasContext(HtmlCanvasElement canvas) { // Apply the tag: Canvas = canvas; Path = new VectorPath(); ImageData_ = new DynamicTexture(); canvas.SetImage(ImageData_); }
/// <summary>Requests for this image to be flushed on the next update.</summary> public void RequestPaint() { if (RefreshRequired) { return; } RefreshRequired = true; // Enqueue NextToUpdate = ToUpdate; ToUpdate = this; }
/// <summary>Removes all content from this image package.</summary> private void Clear() { // Clear any animation: GoingOffDisplay(); Error = null; #if !MOBILE Video = null; #endif Image = null; SPAFile = null; IsVideo = false; Animated = false; IsDynamic = false; DynamicImage = null; }
/// <summary>Applies the image data so it's ready for rendering.</summary> public void UpdateDimensions(LayoutBox box) { int w = (int)box.InnerWidth; int h = (int)box.InnerHeight; DynamicTexture img = ImageData_; if (w == img.Width && h == img.Height) { // No change. Stop there. return; } // Resize the texture (clearing it): img.Resize(w, h, true); }
/// <summary>Fills the specified box region using the given colour.</summary> public void fillRect(int xStart, int yStart, int rectWidth, int rectHeight, Color32 colour) { // First invert y. This is because the canvas API is from the top left corner. DynamicTexture img = ImageData_; int yEnd = img.Height - yStart; int xEnd = xStart + rectWidth; yStart = yEnd - rectHeight; // Clip the region to the available space: if (xStart < 0) { xStart = 0; } if (yStart < 0) { yStart = 0; } if (xEnd > img.Width) { xEnd = img.Width; } if (yEnd > img.Height) { yEnd = img.Height; } // Fill each pixel: for (int y = yStart; y < yEnd; y++) { // Get the index of this row of pixels. int index = (y * img.Width); for (int x = xStart; x < xEnd; x++) { img.Pixels[x + index] = colour; } } img.RequestPaint(); }
/// <summary>Redraw requests are buffered and done in one go by this method.</summary> public static void Update() { if (!SomethingToUpdate) { return; } SomethingToUpdate = false; foreach (KeyValuePair <string, DynamicTexture> kvp in Instances) { DynamicTexture texture = kvp.Value; if (!texture.Refreshing) { continue; } texture.Redraw(); } }
/// <summary>Repaints dynamic textures, writing out their pixels.</summary> public static void Update() { // For each one.. DynamicTexture current = ToUpdate; ToUpdate = null; while (current != null) { DynamicTexture next = current.NextToUpdate; current.NextToUpdate = null; // Repaint: current.Repaint(); // Next: current = next; } }
/// <summary>Applies the image data so it's ready for rendering.</summary> public void ApplyImageData() { // Grab the canvas: Element element = canvas; // Grab its computed style: ComputedStyle computed = element.style.Computed; if (ImageData == null) { ImageData = new DynamicTexture(); } // Resize the texture: ImageData.Resize(computed.PixelWidth, computed.PixelHeight, false); if (ImageData.Width != 0 && ImageData.Height != 0) { if (Package == null) { //We now need a package to actually display it. // Create the package: Package = new ImagePackage(ImageData); // Apply it to the element: if (computed.BGImage == null) { computed.BGImage = new BackgroundImage(element); } computed.BGImage.SetImage(Package); } // Run the change event: element.Run("onchange"); apply(); } }
/// <summary>Fills the current path with a solid colour. The colour used originates from the fillStyle.</summary> public void fill() { if (Path.FirstPathNode == null) { return; } if (Clip_) { // Clip the path first. Clip_ = false; // Clip with a 50px safety zone on all sides for strokes. Path.Clip(-50f, -50f, ImageData.Width + 50f, ImageData.Height + 50f); } if (Rasteriser == null) { // Setup and start the rasteriser: Rasteriser = new Scanner(); Rasteriser.SDFSize = 0; Rasteriser.ScaleY = -1f; Rasteriser.Start(); } // Figure out bounds: Path.RecalculateBounds(); DynamicTexture img = ImageData_; int rWidth = img.Width; int rHeight = img.Height; Rasteriser.Rasterise(Path, img.Pixels, rWidth, 0, rWidth, rHeight, 0f, -rHeight, FillColour, false); img.RequestPaint(); }
/// <summary>Draws the outline of path you created, and doesn't reset the path, using the stroke style.</summary> public void stroke() { // For each line.. DynamicTexture img = ImageData_; VectorPoint node = Path.FirstPathNode; // For each one.. while (node != null) { // Render it as a line (if it has one; checks internally): if (node.HasLine) { // Render the line from the next nodes point of view: node.RenderLine(this); } // Hop to the next one: node = node.Next; } // Request a paint: img.RequestPaint(); }
/// <summary>Creates an image package containing the given dynamic image.</summary> /// <param name="image">The image for this image package. Used to display cached graphics.</param> public ImagePackage(DynamicTexture image) { SetPath("", null); IsDynamic = true; DynamicImage = image; }
/// <summary>Called by the file handler when a dynamic atlas texture was retrieved successfully.</summary> /// <param name="image">The image received.</param> public void GotGraphic(DynamicTexture image){ Clear(); IsDynamic=true; DynamicImage=image; ImageReady(this); }
public override void OnGetGraphic(ImagePackage package, FilePath path) { package.GotGraphic(DynamicTexture.Get(path.Path)); }
/// <summary>Removes all content from this image package.</summary> private void Clear(){ // Clear any animation: GoingOffDisplay(); Error=null; #if !MOBILE Video=null; #endif Image=null; SPAFile=null; IsVideo=false; Animated=false; IsDynamic=false; DynamicImage=null; }
/// <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(); }
//--------------------------------------
public override void Clear() { DynamicImage = null; }
/// <summary>Creates an image package containing the given dynamic image.</summary> /// <param name="image">The image for this image package. Used to display cached graphics.</param> public ImagePackage(DynamicTexture image){ SetPath("",null); IsDynamic=true; DynamicImage=image; }
/// <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(); }
public override void Clear(){ DynamicImage=null; }