コード例 #1
0
ファイル: MeshTable.cs プロジェクト: hidetobara/Painter
        public MeshTable(int area, Vector3[] list)
        {
            if (area < 2) area = 2;
            AREA_LIMIT = area;
            _Points = new List<Vector3>(list);

            Vector3 first = _Points[0];
            float minx = first.x, maxx = first.x, minz = first.z, maxz = first.z;
            foreach(Vector3 p in _Points)
            {
                if (minx > p.x) minx = p.x;
                if (maxx < p.x) maxx = p.x;
                if (minz > p.z) minz = p.z;
                if (maxz < p.z) maxz = p.z;
            }
            Debug.Log("[MeshTable] {" + minx + ">" + maxx + "," + minz + ">" + maxz + "}");

            float xstep = (maxx - minx) / AREA_LIMIT;
            float zstep = (maxz - minz) / AREA_LIMIT;
            _Blocks = new MeshBlock[AREA_LIMIT * AREA_LIMIT];
            for(int xi = 0; xi < AREA_LIMIT; xi++)
            {
                float xstart = minx + xstep * xi;
                float xend = xstart + xstep;
                for(int zi = 0; zi < AREA_LIMIT; zi++)
                {
                    float zstart = minz + zstep * zi;
                    float zend = zstart + zstep;
                    int index = xi * AREA_LIMIT + zi;
                    _Blocks[index] = new MeshBlock(this, xstart, xend, zstart, zend);
                }
            }

            for(int i = 0; i < _Points.Count; i++)
            {
                Vector3 point = _Points[i];
                int xi = (int)((point.x - minx) / xstep);
                int zi = (int)((point.z - minz) / zstep);
                if (xi < 0) xi = 0;
                if (xi >= AREA_LIMIT) xi = AREA_LIMIT - 1;
                if (zi < 0) zi = 0;
                if (zi >= AREA_LIMIT) zi = AREA_LIMIT - 1;
                int index = xi * AREA_LIMIT + zi;
                _Blocks[index].AddIndex(i);
            }

            #if UNITY_EDITOR
            string msg = "";
            for (int b = 0; b < _Blocks.Length; b++)
            {
                msg += " " + _Blocks[b].Count;
                if ((b + 1) % AREA_LIMIT == 0) msg += "\n";
                else msg += ",";
            }
            Debug.Log("[MeshTable]\n" + msg);
            #endif
            if (xstep > zstep) _Around = xstep / 10.0f; else _Around = zstep / 10.0f;
        }
コード例 #2
0
        /// <summary>Draws the given Emoji character.</summary>
        public void DrawEmoji(Glyph character, ref float left, Renderman renderer)
        {
            if (!character.Image.Loaded)
            {
                return;
            }

            BoxRegion screenRegion = renderer.CurrentRegion;
            float     top          = renderer.TopOffset;

            // It's an image (e.g. Emoji).
            AtlasLocation locatedAt = RequireImage(character.Image);

            if (locatedAt == null)
            {
                // It needs to be isolated. Big emoji image!
                return;
            }

            if (CharacterProviders.FixHeight)
            {
                // Set the region:
                screenRegion.Set(left, top, locatedAt.Width, locatedAt.Height);
            }
            else
            {
                screenRegion.Set(left, top, FontSize, FontSize);
            }

            if (screenRegion.Overlaps(renderer.ClippingBoundary))
            {
                // Ensure correct batch:
                renderer.SetupBatch(this, locatedAt.Atlas, null);

                // If the two overlap, this means it's actually visible.
                MeshBlock block = Add(renderer);

                // Set it's colour:
                block.SetColour(renderer.ColorOverlay);

                // And clip our meshblock to fit within boundary:
                block.TextUV = null;

                block.ImageUV = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.ImageUV);

                block.Done(renderer.Transform);
            }

            left += (character.AdvanceWidth) + LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += WordSpacing;
            }
        }
コード例 #3
0
        public override void Paint()
        {
            MeshBlock block = FirstBlock;

            while (block != null)
            {
                block.SetColour(FontColour);
                block.Paint();
                block = block.LocalBlockAfter;
            }
        }
コード例 #4
0
        /// <summary>Sets up this renderman.</summary>
        private void Init()
        {
            Block            = new MeshBlock(this);
            ClippingBoundary = new BoxRegion(0, 0, UnityEngine.Screen.width, UnityEngine.Screen.height);

            if (RootDocument == null)
            {
                HtmlDocument hdoc = new HtmlDocument(this);
                hdoc.SetRawLocation(new Location("resources://", null));
                RootDocument = hdoc;
            }
        }
コード例 #5
0
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            MeshBlock block = GetFirstBlock(renderer);

            if (block == null)
            {
                // This can happen if an animation is requesting that a now offscreen element gets painted only.
                return;
            }

            block.PaintColour(BaseColour * renderer.ColorOverlay);
        }
コード例 #6
0
        public override void Paint()
        {
            // Any meshes in this elements queue should now change colour:
            Color     colour = Element.Style.Computed.ColorOverlay;
            MeshBlock block  = FirstBlock;

            while (block != null)
            {
                block.SetColour(colour);
                block.Paint();
                block = block.LocalBlockAfter;
            }
        }
コード例 #7
0
        /// <summary>Applies any transforms (rotate,scale etc) now. Note that tranforms are post-processes
        /// so they are very fast and mostly done by paint events.</summary>
        public void ApplyTransform()
        {
            MeshBlock block = FirstBlock;

            while (block != null)
            {
                if (block.Transform != null)
                {
                    block.Layout();
                }
                block = block.LocalBlockAfter;
            }
        }
コード例 #8
0
        /// <summary>Transforms all the verts by the given delta matrix. Used during a Paint only.</summary>
        public virtual void ApplyTransform(Matrix4x4 delta, Renderman renderer)
        {
            // Get the first block:
            MeshBlock block = GetFirstBlock(renderer);

            for (int i = 0; i < BlockCount; i++)
            {
                // Transform the verts:
                block.TransformVertices(delta);

                // Seek to the next one:
                block.Next();
            }
        }
コード例 #9
0
        public MeshBlock Add(Renderman renderer)
        {
            // Allocate the block:
            MeshBlock block = renderer.CurrentBatch.Mesh.Allocate(renderer);

            if (Batch == null)
            {
                Batch           = renderer.CurrentBatch;
                FirstBlockIndex = block.Buffer.BlocksBefore + block.BlockIndex;
            }

            BlockCount++;

            return(block);
        }
コード例 #10
0
 MeshBlock GetOrCreateBlock(Vector3 blockCoords)
 {
     if (Blocks.Keys.Contains(blockCoords))
     {
         var block = Blocks[blockCoords];
         return(block);
     }
     else
     {
         var newBlock = new MeshBlock();
         newBlock.Coordinates = blockCoords;
         Blocks.Add(blockCoords, newBlock);
         return(newBlock);
     }
 }
コード例 #11
0
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            Color colour = Colour * renderer.ColorOverlay;

            MeshBlock block = GetFirstBlock(renderer);

            // For each block..
            for (int i = 0; i < BlockCount; i++)
            {
                // Paint the colour:
                block.PaintColour(colour);

                // Go to next block:
                block.Next();
            }
        }
コード例 #12
0
        public override void Paint()
        {
            // Get the computed style:
            ComputedStyle computed = Element.Style.Computed;

            // Any meshes in my queue should now change colour:
            MeshBlock block = FirstBlock;

            if (Colour == null || Colour.Length == 1)
            {
                // Most common case. This is a single colour border.

                // Get the default colour - that's the same as the text colour:
                Color colour = Color.black;

                // Does this border have a colour?
                if (Colour == null)
                {
                    // Grab the text colour if there is one:
                    if (computed.Text != null)
                    {
                        // It's the same as the font colour:
                        colour = computed.Text.FontColour;
                    }
                    else
                    {
                        // Nope - We need to set alpha:
                        colour.a = computed.ColorOverlay.a;
                    }
                }
                else
                {
                    colour = Colour[0];
                }

                // For each block, set the colour:
                while (block != null)
                {
                    block.SetColour(colour);
                    block.Paint();

                    block = block.LocalBlockAfter;
                }

                return;
            }
        }
コード例 #13
0
        /// <summary>Gets the first rendered block of this property. Used during Paint passes.</summary>
        public MeshBlock GetFirstBlock(Renderman renderer)
        {
            if (Batch == null)
            {
                // Layout required.
                return(null);
            }

            // Use the shared block:
            MeshBlock block = renderer.Block;

            // Load into it now:
            block.SetBatchIndex(Batch, FirstBlockIndex);

            // Return it:
            return(block);
        }
コード例 #14
0
ファイル: BackgroundImage.cs プロジェクト: ru-ace/spark
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            // Any meshes in this elements queue should now change colour:
            Color colour = renderer.ColorOverlay;

            MeshBlock block = GetFirstBlock(renderer);

            // For each block..
            for (int i = 0; i < BlockCount; i++)
            {
                // Paint the colour:
                block.PaintColour(colour);

                // Go to next block:
                block.Next();
            }
        }
コード例 #15
0
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            // Any meshes in my queue should now change colour:
            MeshBlock block = GetFirstBlock(renderer);

            if (BaseColour == null || BaseColour.Count == 1)
            {
                // Most common case. This is a single colour border.

                // Get the default colour - that's the same as the text colour:
                Color colour = Color.black;

                // Does this border have a colour?
                if (BaseColour == null)
                {
                    // Grab the text colour if there is one:
                    if (RenderData.Text != null)
                    {
                        // It's the same as the font colour:
                        colour = RenderData.Text.BaseColour * renderer.ColorOverlay;
                    }
                    else
                    {
                        // Nope - We need to set alpha:
                        colour.a = renderer.ColorOverlay.a;
                    }
                }
                else
                {
                    colour = BaseColour[0].GetColour(RenderData, Css.Properties.BorderColor.GlobalProperty) * renderer.ColorOverlay;
                }

                // For each block..
                for (int i = 0; i < BlockCount; i++)
                {
                    // Paint the colour:
                    block.PaintColour(colour);

                    // Go to next block:
                    block.Next();
                }

                return;
            }
        }
コード例 #16
0
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            // Get the top left inner corner (inside margin and border):
            float width  = box.PaddedWidth;
            float height = box.PaddedHeight;
            float top    = box.Y + box.Border.Top;
            float left   = box.X + box.Border.Left;

            // Is it clipped?
            if (renderer.IsInvisible(left, top, width, height))
            {
                // Totally not visible.
                return;
            }

            // Ensure we have a batch (doesn't change graphics or font thus both nulls):
            renderer.SetupBatch(this, null, null);

            // Get the transform:
            Transformation transform = renderer.Transform;

            for (int y = 0; y < 3; y++)
            {
                for (int x = 0; x < 3; x++)
                {
                    // Add it:
                    MeshBlock block = Add(renderer);

                    // Set the UV to that of the solid block colour pixel:
                    block.SetSolidColourUV();

                    // Set the colour - here we set it unevenly to trigger gradients.
                    // block.SetColour(BackingColour * renderer.ColorOverlay);

                    // BoxRegion clipZone=new BoxRegion(left,top,width,height);

                    // Set the verts too:
                    // block.SetClipped(renderer.ClippingBoundary,clipZone,renderer,box.ZIndex-0.006f);

                    block.Done(transform);
                }
            }
        }
コード例 #17
0
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            // Does the given renderer belong to the worldUI?
            if (Renderer != null && renderer == Renderer.Renderer)
            {
                // Yes! We're actually drawing the element. Do nothing.
                return;
            }

            MeshBlock block = GetFirstBlock(renderer);

            if (block == null)
            {
                // This can happen if an animation is requesting that a now offscreen element gets painted only.
                return;
            }

            block.PaintColour(renderer.ColorOverlay);
        }
コード例 #18
0
        /// <summary>Draws an underline (or a strikethrough).</summary>
        public virtual void DrawUnderline(Renderman renderer)
        {
            // Ensure we have a batch:
            renderer.SetupBatch(this, null, null);

            // And get our block ready:
            MeshBlock block = Add(renderer);

            // Set the UV to that of the solid block colour pixel:
            block.SetSolidColourUV();

            // Set the colour:
            block.SetColour(renderer.FontColour);

            // Set the verts:
            block.SetClipped(renderer.ClippingBoundary, renderer.CurrentRegion, renderer, renderer.TextDepth);

            // Ok!
            block.Done(renderer.Transform);
        }
コード例 #19
0
        public override void Paint(LayoutBox box, Renderman renderer)
        {
            // Resolve colour:
            BaseColour = RenderData.computedStyle.Resolve(Css.Properties.ColorProperty.GlobalProperty)
                         .GetColour(RenderData, Css.Properties.ColorProperty.GlobalProperty);

            Color colour = BaseColour * renderer.ColorOverlay;

            MeshBlock block = GetFirstBlock(renderer);

            // For each block..
            for (int i = 0; i < BlockCount; i++)
            {
                // Paint the colour:
                block.PaintColour(colour);

                // Go to next block:
                block.Next();
            }
        }
コード例 #20
0
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        protected virtual void DrawInvertCharacter(ref float left, Renderman renderer)
        {
            BoxRegion screenRegion = renderer.CurrentRegion;
            float     top          = renderer.TopOffset;
            int       index        = renderer.CharacterIndex;

            Glyph character = Text.Characters[index];

            if (character == null)
            {
                return;
            }

            if (Text.Kerning != null)
            {
                left += Text.Kerning[index] * Text.FontSize;
            }

            // Get atlas location (if it has one):
            AtlasLocation locatedAt = character.Location;

            if (locatedAt != null)
            {
                // We're on the atlas!

                float y = top + renderer.TextAscender - ((character.Height + character.MinY) * Text.FontSize);

                float scaleFactor = renderer.TextScaleFactor;

                screenRegion.Set(left + (character.LeftSideBearing * Text.FontSize), y, locatedAt.Width * scaleFactor, locatedAt.Height * scaleFactor);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // True if this character is visible.

                    // Ensure correct batch:
                    renderer.SetupBatch(this, null, locatedAt.Atlas);

                    MeshBlock block = Add(renderer);
                    block.SetColour(renderer.FontColour);
                    block.ApplyOutline();

                    // And clip our meshblock to fit within boundary:
                    block.ImageUV = null;
                    UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.TextUV);

                    if (uvs.Shared)
                    {
                        uvs = new UVBlock(uvs);
                    }

                    // Invert along X:
                    float temp = uvs.MinX;
                    uvs.MinX = uvs.MaxX;
                    uvs.MaxX = temp;

                    // Assign to the block:
                    block.TextUV = uvs;

                    block.Done(renderer.Transform);
                }
            }

            left += (character.AdvanceWidth * Text.FontSize) + Text.LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += Text.WordSpacing;
            }
        }
コード例 #21
0
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        protected virtual void DrawInvertCharacter(ref float left, Renderman renderer)
        {
            BoxRegion screenRegion = renderer.CurrentRegion;
            float     top          = renderer.TopOffset;
            int       index        = renderer.CharacterIndex;

            Glyph character = Characters[index];

            if (character == null)
            {
                return;
            }

            if (Kerning != null)
            {
                left += Kerning[index] * FontSize;
            }

            // Get atlas location (if it has one):
            AtlasLocation locatedAt = character.Location;

            if (locatedAt != null)
            {
                // We're on the atlas!

                float y = top + renderer.TextAscender - ((character.Height + character.MinY) * FontSize);

                float scaleFactor = renderer.TextScaleFactor;

                screenRegion.Set(left + (character.LeftSideBearing * FontSize), y, locatedAt.Width * scaleFactor, locatedAt.Height * scaleFactor);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // True if this character is visible.

                    // Ensure correct batch:
                    renderer.SetupBatch(this, null, locatedAt.Atlas);

                    MeshBlock block = Add(renderer);
                    block.SetColour(renderer.FontColour);
                    block.ApplyOutline();

                    // And clip our meshblock to fit within boundary:

                    // Clip our meshblock to fit within boundary:
                    if (Background != null && Isolated)
                    {
                        // Setup the batch material for this char:
                        Material imageMaterial = Background.Image.Contents.GetImageMaterial(renderer.CurrentShaderSet.Normal);
                        SetBatchMaterial(renderer, imageMaterial);

                        // Reapply text atlas:
                        renderer.CurrentBatch.SetFontAtlas(locatedAt.Atlas);

                        // Apply the image UV's (we're always isolated so these can tile by going out of range):
                        block.ImageUV = block.SetClipped(
                            renderer.ClippingBoundary,
                            screenRegion,
                            renderer,
                            RenderData.computedStyle.ZIndex,
                            Background.ImageLocation,
                            block.ImageUV
                            );
                    }
                    else
                    {
                        block.ImageUV = null;
                    }

                    UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.TextUV);

                    if (uvs.Shared)
                    {
                        uvs = new UVBlock(uvs);
                    }

                    // Invert along X:
                    float temp = uvs.MinX;
                    uvs.MinX = uvs.MaxX;
                    uvs.MaxX = temp;

                    // Assign to the block:
                    block.TextUV = uvs;

                    block.Done(renderer.Transform);
                }
            }

            left += (character.AdvanceWidth * FontSize) + LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += WordSpacing;
            }
        }
コード例 #22
0
        static void ExportFile(string fileName, string destFolder)
        {
            String targetMeshFile = Path.GetFileNameWithoutExtension(fileName) + ".mesh";
            String targetAnimFile = Path.GetFileNameWithoutExtension(fileName) + ".anim";

            Console.WriteLine("Exporting " + targetMeshFile + "...");

            AssimpContext importer = new AssimpContext();
            importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));
            importer.SetConfig(new VertexBoneWeightLimitConfig(4));
            Scene scene = importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessSteps.FlipUVs);

            System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
            customCulture.NumberFormat.NumberDecimalSeparator = ".";

            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            FileStream fs = new FileStream(Path.Combine(destFolder, targetMeshFile), FileMode.Create);
            BinaryWriter dest = new BinaryWriter(fs);

            MeshBlock meshBlock = new MeshBlock(dest, "MX3D");

            List<MeshNode> nodes = new List<MeshNode>();
            addNodes(nodes, scene.RootNode, scene.Meshes[0]);

            for (int j = 0; j < 1; j++)
            {
                MeshBlock groupBlock = new MeshBlock(dest, "XGRP");

                exportGroup(dest, scene.Meshes[j], scene, nodes);

                groupBlock.EndBlock(dest);
            }

            MeshBlock skeletonDataBlock;
            skeletonDataBlock = new MeshBlock(dest, "XSKL");

            UInt32 boneCount = (UInt32)nodes.Count;
            dest.Write(boneCount);

            for (int j = 0; j < nodes.Count; j++)
            {
                exportBone(dest, nodes[j], scene, j);
            }

            skeletonDataBlock.EndBlock(dest);

            meshBlock.EndBlock(dest);

            dest.Close();
            fs.Close();

            for (int i = 0; i < scene.AnimationCount; i++)
            {
                Animation animation = scene.Animations[i];
                String name = animation.Name;
                if (name.Length <= 0)
                {
                    name = Path.GetFileNameWithoutExtension(targetAnimFile);
                    int p = name.LastIndexOf("@");
                    if (p >= 0)
                    {
                        name = name.Substring(p + 1);
                    }
                }

                Console.WriteLine("Exporting " + name + " animation...");

                fs = new FileStream(Path.Combine(destFolder, targetAnimFile), FileMode.Create);
                dest = new BinaryWriter(fs);

                byte[] tagData = Encoding.ASCII.GetBytes("ANIM");
                dest.Write(tagData);

                float FPS = (float)animation.TicksPerSecond;
                dest.Write(FPS);
                byte loop = 1;
                dest.Write(loop);
                float loopPoint = 0.0f;
                dest.Write(loopPoint);
                float animSpeed = 1.0f;
                dest.Write(animSpeed);

                String nextAnim = "";
                exportString(dest, nextAnim);

                UInt32 channelCount = (UInt32)animation.NodeAnimationChannelCount;
                dest.Write(channelCount);
                for (int j = 0; j < channelCount; j++)
                {
                    NodeAnimationChannel channel = animation.NodeAnimationChannels[j];
                    exportString(dest, channel.NodeName);

                    UInt32 posCount = (UInt32)channel.PositionKeyCount;
                    dest.Write(posCount);
                    for (int k = 0; k < posCount; k++)
                    {
                        float t = (float)channel.PositionKeys[k].Time;
                        float x = channel.PositionKeys[k].Value.X;
                        float y = channel.PositionKeys[k].Value.Y;
                        float z = channel.PositionKeys[k].Value.Z;
                        float w = 1.0f;

                        dest.Write(t);
                        dest.Write(x);
                        dest.Write(y);
                        dest.Write(z);
                        dest.Write(w);
                    }

                    UInt32 rotCount = (UInt32)channel.RotationKeyCount;
                    dest.Write(rotCount);
                    for (int k = 0; k < rotCount; k++)
                    {
                        float t = (float)channel.RotationKeys[k].Time;
                        float x = channel.RotationKeys[k].Value.X;
                        float y = channel.RotationKeys[k].Value.Y;
                        float z = channel.RotationKeys[k].Value.Z;
                        float w = channel.RotationKeys[k].Value.W;

                        dest.Write(t);
                        dest.Write(x);
                        dest.Write(y);
                        dest.Write(z);
                        dest.Write(w);
                    }

                    UInt32 scaleCount = (UInt32)channel.ScalingKeyCount;
                    dest.Write(scaleCount);
                    for (int k = 0; k < scaleCount; k++)
                    {
                        float t = (float)channel.ScalingKeys[k].Time;
                        float x = channel.ScalingKeys[k].Value.X;
                        float y = channel.ScalingKeys[k].Value.Y;
                        float z = channel.ScalingKeys[k].Value.Z;
                        float w = 1.0f;

                        dest.Write(t);
                        dest.Write(x);
                        dest.Write(y);
                        dest.Write(z);
                        dest.Write(w);
                    }

                }

                dest.Close();
                fs.Close();
            }
        }
コード例 #23
0
ファイル: BackgroundImage.cs プロジェクト: ru-ace/spark
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            if (Image == null || !Image.Loaded)
            {
                return;
            }

            if (Clipping == BackgroundClipping.Text)
            {
                return;
            }

            if (Image.Contents.Isolate || renderer.RenderMode == RenderMode.NoAtlas || Filtering != FilterMode.Point || ForcedIsolate)
            {
                // SPA is an animation format, so we need a custom texture atlas to deal with it.
                // This is because the frames of any animation would quickly exhaust our global texture atlas.
                // So to get a custom atlas, we must isolate this property.
                Isolate();
            }
            else
            {
                // Reverse isolation, if we are isolated already:
                Include();
            }

            // Get the full shape of the element:

            float width;
            float height;
            float minX;
            float minY;

            if (renderer.ViewportBackground)
            {
                // Applying to whole background:
                BoxRegion viewport = renderer.Viewport;

                minY   = (int)viewport.Y;
                minX   = (int)viewport.X;
                width  = (int)viewport.Width;
                height = (int)viewport.Height;

                renderer.ViewportBackground = false;
            }
            else
            {
                width  = (int)(box.PaddedWidth);
                height = (int)(box.PaddedHeight);
                minY   = (int)(box.Y + box.Border.Top);
                minX   = (int)(box.X + box.Border.Left);
            }

            if (width == 0 || height == 0)
            {
                if (Visible)
                {
                    SetVisibility(false);
                }
                return;
            }

            // Tell the image that the box has likely changed - this allows it to redraw (e.g. SVGs):
            float trueImageWidth;
            float trueImageHeight;

            Image.Contents.OnLayout(RenderData, box, out trueImageWidth, out trueImageHeight);

            BoxRegion boundary = new BoxRegion(minX, minY, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Texture time - get it's location on that atlas:
            AtlasLocation locatedAt = ImageLocation;

            if (locatedAt == null)
            {
                // We're not using the atlas here.

                if (!Isolated)
                {
                    Isolate();
                }

                locatedAt = new AtlasLocation(trueImageWidth, trueImageHeight);
            }

            // Isolation is all done - safe to setup the batch now:
            renderer.SetupBatch(this, locatedAt.Atlas, null);

            // Great - Use locatedAt.Width/locatedAt.Height - this removes any risk of overflowing into some other image.

            int   imageCountX = 1;
            int   imageCountY = 1;
            float imageWidth  = trueImageWidth * RenderData.ValueScale;
            float imageHeight = trueImageHeight * RenderData.ValueScale;
            bool  autoX       = false;
            bool  autoY       = false;

            if (SizeX != null)
            {
                if (SizeX.IsAuto)
                {
                    autoX = true;
                }
                else
                {
                    imageWidth = SizeX.GetDecimal(RenderData, Css.Properties.BackgroundSize.GlobalPropertyX);
                }
            }

            if (SizeY != null)
            {
                if (SizeY.IsAuto)
                {
                    autoY = true;
                }
                else
                {
                    imageHeight = SizeY.GetDecimal(RenderData, Css.Properties.BackgroundSize.GlobalPropertyY);
                }
            }

            if (autoX)
            {
                imageWidth = imageHeight * trueImageWidth / trueImageHeight;
            }
            else if (autoY)
            {
                imageHeight = imageWidth * trueImageHeight / trueImageWidth;
            }

            // offsetX and offsetY are the images position offset from where it should be (e.g. x of -200 means it's 200px left)

            // Apply the offset origin:
            float offsetX = OffsetOriginX * (width - imageWidth);
            float offsetY = OffsetOriginY * (height - imageHeight);

            float offset;

            // Resolve the offset values, if there is any:
            if (OffsetX != null)
            {
                offset = OffsetX.GetDecimal(RenderData, ValueAxis.X);

                if (OffsetOriginX == 1f)
                {
                    offsetX -= offset;
                }
                else
                {
                    offsetX += offset;
                }
            }

            if (OffsetY != null)
            {
                offset = OffsetY.GetDecimal(RenderData, ValueAxis.Y);

                if (OffsetOriginY == 1f)
                {
                    offsetY -= offset;
                }
                else
                {
                    offsetY += offset;
                }
            }

            if (RepeatX)
            {
                // Get the rounded up number of images:
                imageCountX = (int)Math.Ceiling(width / imageWidth);

                if (offsetX != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountX++;
                }
            }

            if (RepeatY)
            {
                // Get the rounded up number of images:
                imageCountY = (int)Math.Ceiling(height / imageHeight);
                if (offsetY != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountY++;
                }
            }

            float blockX = minX + offsetX;
            float blockY = minY + offsetY;

            if (RepeatX && offsetX > 0)
            {
                // We're repeating and the image is offset by a +ve number.
                // This means a small gap, OffsetX px wide, is open on this left side.
                // So to fill it, we need to offset this first image by a much bigger number - the value imageWidth-OffsetX.
                blockX -= (imageWidth - offsetX);
                // This results in the first image having OffsetX pixels exposed in the box - this is what we want.
            }

            if (RepeatY && offsetY > 0)
            {
                // Similar thing to above:
                blockY -= (imageHeight - offsetY);
            }

            BoxRegion screenRegion = new BoxRegion();

            bool  first  = true;
            float startX = blockX;
            Color colour = renderer.ColorOverlay;
            float zIndex = (RenderData.computedStyle.ZIndex - 0.003f);

            Transformation transform = renderer.Transform;

            for (int y = 0; y < imageCountY; y++)
            {
                for (int x = 0; x < imageCountX; x++)
                {
                    // Draw at blockX/blockY.
                    screenRegion.Set(blockX, blockY, imageWidth, imageHeight);

                    if (screenRegion.Overlaps(boundary))
                    {
                        // If the two overlap, this means it's actually visible.
                        MeshBlock block = Add(renderer);

                        if (first)
                        {
                            first = false;

                            if (Isolated)
                            {
                                // Set current material:
                                SetBatchMaterial(renderer, Image.Contents.GetImageMaterial(renderer.CurrentShaderSet.Isolated));
                            }
                        }

                        // Set its colour:
                        block.SetColour(colour);

                        // And clip our meshblock to fit within boundary:
                        block.TextUV  = null;
                        block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, locatedAt, block.ImageUV);

                        block.Done(transform);
                    }

                    blockX += imageWidth;
                }
                blockX  = startX;
                blockY += imageHeight;
            }
        }
コード例 #24
0
        static void exportGroup(BinaryWriter dest, Assimp.Mesh mesh, Assimp.Scene scene, List<MeshNode> nodes)
        {
            UInt32 vertexFormat = VF(vertexPosition);

            if (mesh.HasBones)
                vertexFormat |= VF(vertexBone);

            if (mesh.HasNormals)
                vertexFormat |= VF(vertexNormal);

            if (mesh.HasTangentBasis)
                vertexFormat |= VF(vertexTangent) | VF(vertexBiTangent);

            for (int i = 0; i < mesh.TextureCoordinateChannelCount; i++  )
            {
                vertexFormat |= VF(vertexUV0 + i);
            }

            dest.Write(vertexFormat);
            exportString(dest, mesh.Name);

            UInt16 vertexCount = (UInt16 ) mesh.VertexCount;

            UInt32 meshFlags = 0;
            dest.Write(meshFlags);
            dest.Write(vertexCount);

            MeshBlock vertexDataBlock;
            vertexDataBlock = new MeshBlock(dest, "VATX");
            dest.Write(vertexPosition);
            dest.Write(typeVector3D);
            Matrix4x4 mat = scene.RootNode.Transform;
            for (int i = 0; i < mesh.VertexCount; i++)
            {
                Vector3D V = new Vector3D();
                V.X = mesh.Vertices[i].X;
                V.Y = mesh.Vertices[i].Y;
                V.Z = mesh.Vertices[i].Z;

                dest.Write(V.X);
                dest.Write(V.Y);
                dest.Write(V.Z);
            }
            vertexDataBlock.EndBlock(dest);

            /*if (mesh.HasVertexColors(0))
            {
                vertexDataBlock = new MeshBlock(w, "VATX");
                dest.Write(vertexColor);
                dest.Write(typeColor);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    byte R = (byte)(mesh.VertexColorChannels[0][i].R * 255.0f);
                    byte G = (byte)(mesh.VertexColorChannels[0][i].G * 255.0f);
                    byte B = (byte)(mesh.VertexColorChannels[0][i].B * 255.0f);
                    byte A = (byte)(mesh.VertexColorChannels[0][i].A * 255.0f);

                    UInt32 color = (UInt32) (R + (G << 8) + (B << 16) + (A << 24));
                    dest.Write(color);
                }
                vertexDataBlock.EndBlock(w);
            }*/

            if (mesh.HasBones)
            {
                vertexDataBlock = new MeshBlock(dest, "VATX");
                dest.Write(vertexBone);
                dest.Write(typeFloat);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    int boneIndex = -1;
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        var bone = nodes[j].bone;
                        if (bone == null)
                            continue;

                        if (bone.HasVertexWeights)
                        {
                            for (int k=0; k<bone.VertexWeightCount; k++)
                            if (bone.VertexWeights[k].VertexID == i)
                            {
                                boneIndex = j;
                                break;
                            }
                        }

                        if (boneIndex >=0)
                        {
                            break;
                        }
                    }

                    boneIndex++;

                    float boneID = boneIndex;
                    dest.Write(boneID);
                }
                vertexDataBlock.EndBlock(dest);
            }

            if (mesh.HasNormals)
            {
                vertexDataBlock = new MeshBlock(dest, "VATX");
                dest.Write(vertexNormal);
                dest.Write(typeVector3D);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    dest.Write(mesh.Normals[i].X);
                    dest.Write(mesh.Normals[i].Y);
                    dest.Write(mesh.Normals[i].Z);
                }
                vertexDataBlock.EndBlock(dest);
            }

            if (mesh.HasTangentBasis)
            {
                vertexDataBlock = new MeshBlock(dest, "VATX");
                dest.Write(vertexTangent);
                dest.Write(typeVector3D);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    dest.Write(mesh.Tangents[i].X);
                    dest.Write(mesh.Tangents[i].Y);
                    dest.Write(mesh.Tangents[i].Z);
                }
                vertexDataBlock.EndBlock(dest);

                vertexDataBlock = new MeshBlock(dest, "VATX");
                dest.Write(vertexBiTangent);
                dest.Write(typeVector3D);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    dest.Write(mesh.BiTangents[i].X);
                    dest.Write(mesh.BiTangents[i].Y);
                    dest.Write(mesh.BiTangents[i].Z);
                }
                vertexDataBlock.EndBlock(dest);
            }

            for (int j = 0; j < mesh.TextureCoordinateChannelCount; j++)
            {
                vertexDataBlock = new MeshBlock(dest, "VATX");
                byte uvSlot = (byte)(vertexUV0 + j);
                dest.Write(uvSlot);
                dest.Write(typeVector2D);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    dest.Write(mesh.TextureCoordinateChannels[j][i].X);
                    dest.Write(mesh.TextureCoordinateChannels[j][i].Y);
                    //dest.Write(mesh.TextureCoordinateChannels[j][i].Z);
                }
                vertexDataBlock.EndBlock(dest);
            }

            MeshBlock lodDataBlock;
            lodDataBlock = new MeshBlock(dest, "GLOD");
            byte lodLevel = 0;
            UInt32 triangleCount = (UInt32) mesh.FaceCount;
            dest.Write(lodLevel);
            dest.Write(triangleCount);
            for (int i = 0; i < mesh.FaceCount; i++)
            {
                UInt16 A = (UInt16) mesh.Faces[i].Indices[0];
                UInt16 B = (UInt16) mesh.Faces[i].Indices[1];
                UInt16 C = (UInt16) mesh.Faces[i].Indices[2];

                dest.Write(A);
                dest.Write(B);
                dest.Write(C);
            }
            lodDataBlock.EndBlock(dest);

            MeshBlock textureDataBlock;
            textureDataBlock = new MeshBlock(dest, "MDIF");
            UInt32 diffuseColor = 0xFFFFFFFF;
            dest.Write(diffuseColor);
            exportString(dest, scene.Materials[mesh.MaterialIndex].TextureDiffuse.FilePath);
            textureDataBlock.EndBlock(dest);
        }
コード例 #25
0
        public void Render(float alpha, float cornerX, float cornerY)
        {
            // Grab the renderer:
            Renderman renderer = RoundCorners.Renderer;

            // Get the z-Index:
            float zIndex = renderer.Depth + 0.006f;

            // Figure out where half way is (divide by 2):
            int halfway = (BlocksRequired >> 1);

            Color colour;

            if (Border.Colour == null)
            {
                if (RoundCorners.Computed.Text != null)
                {
                    // Same as the font colour:
                    colour = RoundCorners.Computed.Text.FontColour;
                }
                else
                {
                    // Get the default colour:
                    colour = Color.black;

                    // Alpha is required:
                    colour.a = alpha;
                }
            }
            else if (Border.Colour.Length == 1)
            {
                // Get the only colour:
                colour = Border.Colour[0];
            }
            else
            {
                // Get the first colour:
                colour = Border.Colour[FromIndex];
            }

            // Grab the clipping boundary:
            BoxRegion clip = renderer.ClippingBoundary;

            // Make it relative to the corners location:
            float minClipX = clip.X - cornerX;
            float minClipY = clip.Y - cornerY;
            float maxClipX = clip.MaxX - cornerX;
            float maxClipY = clip.MaxY - cornerY;

            // For each block..
            for (int i = 0; i < BlocksRequired; i++)
            {
                // Get a block:
                MeshBlock block = Border.Add();

                // Read the outer arc:
                Vector2 outerPointA = OuterArc[i];

                // Figure out the bounding box (constant for a particular block).
                float minX = outerPointA.x;
                float maxX = minX;
                float minY = outerPointA.y;
                float maxY = minY;

                Vector2 outerPointB = OuterArc[i + 1];

                // Update the bounding box:
                if (outerPointB.x < minX)
                {
                    minX = outerPointB.x;
                }
                else if (outerPointB.x > maxX)
                {
                    maxX = outerPointB.x;
                }

                if (outerPointB.y < minY)
                {
                    minY = outerPointB.y;
                }
                else if (outerPointB.y > maxY)
                {
                    maxY = outerPointB.y;
                }

                // Line segment A->B on the "outer" arc.

                // Read the inner arc:
                Vector2 innerPointA = InnerArc[i];

                // Update the bounding box:
                if (innerPointA.x < minX)
                {
                    minX = innerPointA.x;
                }
                else if (innerPointA.x > maxX)
                {
                    maxX = innerPointA.x;
                }

                if (innerPointA.y < minY)
                {
                    minY = innerPointA.y;
                }
                else if (innerPointA.y > maxY)
                {
                    maxY = innerPointA.y;
                }

                Vector2 innerPointB = InnerArc[i + 1];

                // Update the bounding box:
                if (innerPointB.x < minX)
                {
                    minX = innerPointB.x;
                }
                else if (innerPointB.x > maxX)
                {
                    maxX = innerPointB.x;
                }

                if (innerPointB.y < minY)
                {
                    minY = innerPointB.y;
                }
                else if (innerPointB.y > maxY)
                {
                    maxY = innerPointB.y;
                }

                // How does our bounding box compare to the clipping region?
                if (maxX < minClipX)
                {
                    continue;
                }
                else if (minX > maxClipX)
                {
                    continue;
                }

                if (maxY < minClipY)
                {
                    continue;
                }
                else if (minY > maxClipY)
                {
                    continue;
                }

                // Line segment A->B on the "inner" arc.

                // Set the UV to that of the solid block colour pixel:
                block.SetSolidColourUV();

                // Get the border colour:
                if (i == halfway)
                {
                    // Get the next colour:

                    if (Border.Colour != null && Border.Colour.Length != 1)
                    {
                        colour = Border.Colour[ToIndex];
                    }
                }

                // Set the border colour:
                block.SetColour(colour);

                // Apply the block region:
                block.VertexTopLeft  = renderer.PixelToWorldUnit(cornerX + outerPointA.x, cornerY + outerPointA.y, zIndex);
                block.VertexTopRight = renderer.PixelToWorldUnit(cornerX + outerPointB.x, cornerY + outerPointB.y, zIndex);

                block.VertexBottomLeft  = renderer.PixelToWorldUnit(cornerX + innerPointA.x, cornerY + innerPointA.y, zIndex);
                block.VertexBottomRight = renderer.PixelToWorldUnit(cornerX + innerPointB.x, cornerY + innerPointB.y, zIndex);
            }
        }
コード例 #26
0
        protected override void Layout()
        {
            if (Characters == null || FontToDraw == null || Characters.Length == 0)
            {
                return;
            }

            // The blocks we allocate here come from FontToDraw.
            // They use the same renderer and same layout service, but just a different mesh.
            // This is to enable potentially very large font atlases with multiple fonts.
            ComputedStyle computed = Element.Style.Computed;
            Renderman     renderer = Element.Document.Renderer;

            float top  = computed.OffsetTop + computed.StyleOffsetTop;
            float left = computed.OffsetLeft + computed.StyleOffsetLeft;

            // Should we auto-alias the text?

            // Note that this property "drags" to following elements which is correct.
            // We don't really want to break batching chains for aliasing.

            if (Alias == float.MaxValue)
            {
                // Yep! Note all values here are const.
                float aliasing = Fonts.AutoAliasOffset - ((FontSize - Fonts.AutoAliasRelative) * Fonts.AutoAliasRamp);

                if (aliasing > 0.1f)
                {
                    renderer.FontAliasing = aliasing;
                }
            }
            else
            {
                // Write aliasing:
                renderer.FontAliasing = Alias;
            }

            if (Extrude != 0f)
            {
                // Compute the extrude now:
                if (Text3D == null)
                {
                    Text3D = Get3D(FontSize, FontColour, ref left, ref top);
                }
                else
                {
                    // Update it.
                }

                return;
            }
            else
            {
                Text3D = null;
            }


            if (!AllWhitespace)
            {
                // Firstly, make sure the batch is using the right font texture.
                // This may generate a new batch if the font doesn't match the previous or existing font.

                // Get the full shape of the element:
                int width  = computed.PaddedWidth;
                int height = computed.PaddedHeight;
                int minY   = computed.OffsetTop + computed.BorderTop;
                int minX   = computed.OffsetLeft + computed.BorderLeft;

                BoxRegion boundary = new BoxRegion(minX, minY, width, height);

                if (!boundary.Overlaps(renderer.ClippingBoundary))
                {
                    if (Visible)
                    {
                        SetVisibility(false);
                    }

                    return;
                }
                else if (!Visible)
                {
                    // ImageLocation will allocate here if it's needed.
                    SetVisibility(true);
                }
            }

            float     zIndex       = computed.ZIndex;
            BoxRegion screenRegion = new BoxRegion();

            // First up, underline.
            if (TextLine != null)
            {
                // We have one. Locate it next.
                float lineWeight = (FontToDraw.StrikeSize * FontSize);
                float yOffset    = 0f;

                switch (TextLine.Type)
                {
                case TextLineType.Underline:
                    yOffset = Ascender + lineWeight;
                    break;

                case TextLineType.StrikeThrough:
                    yOffset = (FontToDraw.StrikeOffset * FontSize);
                    yOffset = Ascender - yOffset;
                    break;

                case TextLineType.Overline:
                    yOffset = (lineWeight * 2f);
                    break;
                }

                Color lineColour = FontColour;

                if (TextLine.ColourOverride)
                {
                    lineColour = TextLine.Colour;
                }

                screenRegion.Set(left, top + yOffset, computed.PixelWidth, lineWeight);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // Ensure we have a batch:
                    SetupBatch(null, null);

                    // This region is visible. Clip it:
                    screenRegion.ClipBy(renderer.ClippingBoundary);
                    // And get our block ready:
                    MeshBlock block = Add();
                    // Set the UV to that of the solid block colour pixel:
                    block.SetSolidColourUV();
                    // Set the colour:
                    block.SetColour(lineColour);

                    block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, zIndex);
                }
            }


            // Next, render the characters.
            // If we're rendering from right to left, flip the punctuation over.

            // Is the word itself rightwards?
            bool rightwardWord = false;

            if (StartPunctuationCount < Characters.Length)
            {
                // Is the first actual character a rightwards one?
                Glyph firstChar = Characters[StartPunctuationCount];

                if (firstChar != null)
                {
                    rightwardWord = firstChar.Rightwards;
                }
            }

            // Right to left (e.g. arabic):
            if (computed.DrawDirection == DirectionType.RTL)
            {
                int end = Characters.Length - EndPunctuationCount;

                // Draw the punctuation from the end of the string first, backwards:
                if (EndPunctuationCount > 0)
                {
                    for (int i = Characters.Length - 1; i >= end; i--)
                    {
                        DrawInvertCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                    }
                }

                if (rightwardWord)
                {
                    // Render the word itself backwards.

                    for (int i = end - 1; i >= StartPunctuationCount; i--)
                    {
                        DrawCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                    }
                }
                else
                {
                    // Draw the middle characters:
                    for (int i = StartPunctuationCount; i < end; i++)
                    {
                        DrawCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                    }
                }

                // Draw the punctuation from the start of the string last, backwards:

                if (StartPunctuationCount > 0)
                {
                    for (int i = StartPunctuationCount - 1; i >= 0; i--)
                    {
                        DrawInvertCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                    }
                }
            }
            else if (rightwardWord)
            {
                // Render the word itself backwards.

                for (int i = Characters.Length - 1; i >= 0; i--)
                {
                    DrawCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                }
            }
            else
            {
                // Draw it as is.

                for (int i = 0; i < Characters.Length; i++)
                {
                    DrawCharacter(i, ref left, top, renderer, zIndex, screenRegion);
                }
            }
        }
コード例 #27
0
        internal override void Layout(LayoutBox box, Renderman renderer)
        {
            // Dimensions:
            float width  = box.Width;
            float height = box.Height;

            if (Renderer == null)
            {
                // Create the FWUI now:
                Renderer = new FlatWorldUI("#Internal-PowerUI-Raster-" + RasterID, (int)width, (int)height);
                RasterID++;

                if (Filter != null)
                {
                    // Set source:
                    Filter.Set("source0", Renderer.Texture);
                }

                // Grab the output texture:
                Output = Renderer.Texture;
            }

            // Does the given renderer belong to the worldUI?
            if (renderer == Renderer.Renderer)
            {
                // Yes! We're actually drawing the element.

                return;
            }

            // Next we'll draw the rastered image.
            // It's essentially just the output from the renderer.

            // Get the top left inner corner (inside margin and border):
            float top  = box.Y;
            float left = box.X;

            // Update the FlatWorldUI next:
            UpdateRenderer(box, width, height);

            // Always isolated:
            Isolate();

            // Make sure the renderer stalls and doesn't draw anything else of this element or its kids.
            renderer.StallStatus = 2;

            // Setup boundary:
            BoxRegion boundary = new BoxRegion(left, top, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            // Texture time - get its location on that atlas:
            if (LocatedAt == null)
            {
                LocatedAt = new AtlasLocation(width, height);
            }
            else
            {
                // Dimensions changed?
                int w = (int)width;
                int h = (int)height;

                if (LocatedAt.Width != w || LocatedAt.Height != h)
                {
                    // Update it:
                    LocatedAt.UpdateFixed(width, height);
                }
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Ensure we have a batch:
            renderer.SetupBatch(this, null, null);

            if (Material == null)
            {
                // Create the material now using the isolated shader:
                Material = new Material(renderer.CurrentShaderSet.Isolated);

                // Hook up the output:
                Material.SetTexture("_MainTex", Output);
            }

            // Allocate the block:
            MeshBlock block = Add(renderer);

            // Set current material:
            SetBatchMaterial(renderer, Material);

            // Set the (overlay) colour:
            block.SetColour(renderer.ColorOverlay);
            block.TextUV = null;

            // Z-index (same as a background-image):
            float zIndex = (RenderData.computedStyle.ZIndex - 0.003f);

            BoxRegion screenRegion = new BoxRegion();

            screenRegion.Set(left, top, width, height);

            // Setup the block:
            block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, LocatedAt, block.ImageUV);

            // Flush it:
            block.Done(renderer.Transform);
        }
コード例 #28
0
//--------------------------------------
コード例 #29
0
        protected override void Layout()
        {
            if (Image == null || !Image.Loaded())
            {
                return;
            }

            if (Clipping == BackgroundClipping.Text)
            {
                return;
            }

            Renderman renderer = Element.Document.Renderer;

            if (Image.Animated || Image.IsDynamic || renderer.RenderMode == RenderMode.NoAtlas || Filtering != FilterMode.Point || ForcedIsolate)
            {
                // SPA is an animation format, so we need a custom texture atlas to deal with it.
                // This is because the frames of any animation would quickly exhaust our global texture atlas.
                // So to get a custom atlas, we must isolate this property.
                Isolate();
            }
            else if (Image.IsVideo)
            {
                // Similarly with a video, we need to isolate it aswell.
                Isolate();

                                #if !MOBILE
                if (!Image.Video.isPlaying && Element["autoplay"] != null)
                {
                    // Play now:
                    Image.Video.Play();

                    // Fire an onplay event:
                    Element.Run("onplay");

                    // Clear:
                    Element["autoplay"] = null;
                }
                                #endif
            }
            else
            {
                // Reverse isolation, if we are isolated already:
                Include();
            }

            ComputedStyle computed = Element.Style.Computed;

            // Get the full shape of the element:
            int width  = computed.PaddedWidth;
            int height = computed.PaddedHeight;
            int minY   = computed.OffsetTop + computed.BorderTop;
            int minX   = computed.OffsetLeft + computed.BorderLeft;

            if (width == 0 || height == 0)
            {
                if (Visible)
                {
                    SetVisibility(false);
                }
                return;
            }

            BoxRegion boundary = new BoxRegion(minX, minY, width, height);

            if (!boundary.Overlaps(renderer.ClippingBoundary))
            {
                if (Visible)
                {
                    SetVisibility(false);
                }

                return;
            }
            else if (!Visible)
            {
                // ImageLocation will allocate here if it's needed.
                SetVisibility(true);
            }

            boundary.ClipBy(renderer.ClippingBoundary);

            // Texture time - get it's location on that atlas:
            AtlasLocation locatedAt = ImageLocation;

            if (locatedAt == null)
            {
                // We're not using the atlas here.

                if (!Isolated)
                {
                    Isolate();
                }

                int imgWidth  = Image.Width();
                int imgHeight = Image.Height();
                locatedAt = new AtlasLocation(0, 0, imgWidth, imgHeight, imgWidth, imgHeight);
            }

            // Isolation is all done - safe to setup the batch now:
            SetupBatch(locatedAt.Atlas, null);

            // Great - Use locatedAt.Width/locatedAt.Height - this removes any risk of overflowing into some other image.

            int  imageCountX     = 1;
            int  imageCountY     = 1;
            int  trueImageWidth  = locatedAt.Width;
            int  trueImageHeight = locatedAt.Height;
            int  imageWidth      = trueImageWidth;
            int  imageHeight     = trueImageHeight;
            bool autoX           = false;
            bool autoY           = false;

            if (Image.PixelPerfect)
            {
                imageWidth  = (int)(imageWidth * ScreenInfo.ResolutionScale);
                imageHeight = (int)(imageWidth * ScreenInfo.ResolutionScale);
            }

            if (SizeX != null)
            {
                if (SizeX.Single != 0f)
                {
                    imageWidth = (int)(width * SizeX.Single);
                }
                else if (SizeX.PX != 0)
                {
                    imageWidth = SizeX.PX;
                }
                else if (SizeX.IsAuto())
                {
                    autoX = true;
                }
            }

            if (SizeY != null)
            {
                if (SizeY.Single != 0f)
                {
                    imageHeight = (int)(height * SizeY.Single);
                }
                else if (SizeY.PX != 0)
                {
                    imageHeight = SizeY.PX;
                }
                else if (SizeY.IsAuto())
                {
                    autoY = true;
                }
            }

            if (autoX)
            {
                imageWidth = imageHeight * trueImageWidth / trueImageHeight;
            }
            else if (autoY)
            {
                imageHeight = imageWidth * trueImageHeight / trueImageWidth;
            }

            // offsetX and offsetY are the images position offset from where it should be (e.g. x of -200 means it's 200px left)

            // Resolve the true offset values:
            int offsetX = 0;
            int offsetY = 0;

            if (OffsetX != null)
            {
                // Resolve a potential mixed % and px:
                offsetX = OffsetX.GetMixed(width - imageWidth);
            }

            if (OffsetY != null)
            {
                // Resolve a potential mixed % and px:
                offsetY = OffsetY.GetMixed(height - imageHeight);
            }

            if (RepeatX)
            {
                // Get the rounded up number of images:
                imageCountX = (width - 1) / imageWidth + 1;

                if (offsetX != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountX++;
                }
            }

            if (RepeatY)
            {
                // Get the rounded up number of images:
                imageCountY = (height - 1) / imageHeight + 1;
                if (offsetY != 0)
                {
                    // If we have an offset, another image is introduced.
                    imageCountY++;
                }
            }

            int blockX = minX + offsetX;
            int blockY = minY + offsetY;

            if (RepeatX && offsetX > 0)
            {
                // We're repeating and the image is offset by a +ve number.
                // This means a small gap, OffsetX px wide, is open on this left side.
                // So to fill it, we need to offset this first image by a much bigger number - the value imageWidth-OffsetX.
                blockX -= (imageWidth - offsetX);
                // This results in the first image having OffsetX pixels exposed in the box - this is what we want.
            }

            if (RepeatY && offsetY > 0)
            {
                // Similar thing to above:
                blockY -= (imageHeight - offsetY);
            }

            BoxRegion screenRegion = new BoxRegion();

            bool  first  = true;
            int   startX = blockX;
            Color colour = computed.ColorOverlay;
            float zIndex = (computed.ZIndex - 0.003f);

            for (int y = 0; y < imageCountY; y++)
            {
                for (int x = 0; x < imageCountX; x++)
                {
                    // Draw at blockX/blockY.
                    screenRegion.Set(blockX, blockY, imageWidth, imageHeight);

                    if (screenRegion.Overlaps(boundary))
                    {
                        // If the two overlap, this means it's actually visible.
                        MeshBlock block = Add();

                        if (Image.Animated && first)
                        {
                            first = false;
                            // Make sure we have an instance:
                            Image.GoingOnDisplay();
                            block.ParentMesh.SetMaterial(Image.Animation.AnimatedMaterial);
                        }
                        else if (Image.IsVideo && first)
                        {
                            first = false;
                            block.ParentMesh.SetMaterial(Image.VideoMaterial);
                        }
                        else if (Isolated && first)
                        {
                            first = false;
                            block.ParentMesh.SetMaterial(Image.ImageMaterial);
                        }

                        // Set it's colour:
                        block.SetColour(colour);

                        // And clip our meshblock to fit within boundary:
                        block.TextUV  = null;
                        block.ImageUV = block.SetClipped(boundary, screenRegion, renderer, zIndex, locatedAt, block.ImageUV);
                    }

                    blockX += imageWidth;
                }
                blockX  = startX;
                blockY += imageHeight;
            }
        }
コード例 #30
0
ファイル: RoundCorner.cs プロジェクト: ru-ace/spark
        public void Render(LayoutBox box, Renderman renderer, float cornerX, float cornerY)
        {
            if (OuterArc == null)
            {
                RecomputeArcs(box.Border);
            }
            else if (InnerArc == null)
            {
                RecomputeInnerArc(box.Border);
            }

            // Get the z-Index:
            float zIndex = RoundCorners.Computed.MaxZIndex + 0.006f;

            // Figure out where half way is (divide by 2):
            int halfway = (BlocksRequired >> 1);

            Color colour = Colour;

            // Grab the clipping boundary:
            BoxRegion clip = renderer.ClippingBoundary;

            // Make it relative to the corners location:
            float minClipX = clip.X - cornerX;
            float minClipY = clip.Y - cornerY;
            float maxClipX = clip.MaxX - cornerX;
            float maxClipY = clip.MaxY - cornerY;

            // For each block..
            for (int i = 0; i < BlocksRequired; i++)
            {
                // Read the outer arc:
                Vector2 outerPointA = OuterArc[i];

                // Figure out the bounding box (constant for a particular block).
                float minX = outerPointA.x;
                float maxX = minX;
                float minY = outerPointA.y;
                float maxY = minY;

                Vector2 outerPointB = OuterArc[i + 1];

                // Update the bounding box:
                if (outerPointB.x < minX)
                {
                    minX = outerPointB.x;
                }
                else if (outerPointB.x > maxX)
                {
                    maxX = outerPointB.x;
                }

                if (outerPointB.y < minY)
                {
                    minY = outerPointB.y;
                }
                else if (outerPointB.y > maxY)
                {
                    maxY = outerPointB.y;
                }

                // Line segment A->B on the "outer" arc.

                // Read the inner arc:
                Vector2 innerPointA = InnerArc[i];

                // Update the bounding box:
                if (innerPointA.x < minX)
                {
                    minX = innerPointA.x;
                }
                else if (innerPointA.x > maxX)
                {
                    maxX = innerPointA.x;
                }

                if (innerPointA.y < minY)
                {
                    minY = innerPointA.y;
                }
                else if (innerPointA.y > maxY)
                {
                    maxY = innerPointA.y;
                }

                Vector2 innerPointB = InnerArc[i + 1];

                // Update the bounding box:
                if (innerPointB.x < minX)
                {
                    minX = innerPointB.x;
                }
                else if (innerPointB.x > maxX)
                {
                    maxX = innerPointB.x;
                }

                if (innerPointB.y < minY)
                {
                    minY = innerPointB.y;
                }
                else if (innerPointB.y > maxY)
                {
                    maxY = innerPointB.y;
                }

                // How does our bounding box compare to the clipping region?
                if (maxX < minClipX)
                {
                    continue;
                }
                else if (minX > maxClipX)
                {
                    continue;
                }

                if (maxY < minClipY)
                {
                    continue;
                }
                else if (minY > maxClipY)
                {
                    continue;
                }

                // Line segment A->B on the "inner" arc.

                // Get a block:
                MeshBlock block = Border.Add(renderer);

                // Set the UV to that of the solid block colour pixel:
                block.SetSolidColourUV();

                // Get the border colour:
                if (i == halfway)
                {
                    // Get the next colour:

                    if (Border.BaseColour != null && Border.BaseColour.Count != 1)
                    {
                        colour = Border.BaseColour[ToIndex].GetColour(Border.RenderData, Css.Properties.BorderColor.GlobalProperty) * renderer.ColorOverlay;
                    }
                }

                // Set the border colour:
                block.SetColour(colour);

                // Apply the block region:
                block.VertexTopLeft  = renderer.PixelToWorldUnit(cornerX + outerPointA.x, cornerY + outerPointA.y, zIndex);
                block.VertexTopRight = renderer.PixelToWorldUnit(cornerX + outerPointB.x, cornerY + outerPointB.y, zIndex);

                block.VertexBottomLeft  = renderer.PixelToWorldUnit(cornerX + innerPointA.x, cornerY + innerPointA.y, zIndex);
                block.VertexBottomRight = renderer.PixelToWorldUnit(cornerX + innerPointB.x, cornerY + innerPointB.y, zIndex);

                block.Done(renderer.Transform);
            }
        }
コード例 #31
0
        /// <summary>Draws a character with x-inverted UV's. Used for rendering e.g. "1 < 2" in right-to-left.</summary>
        private void DrawInvertCharacter(int index, ref float left, float top, Renderman renderer, float zIndex, BoxRegion screenRegion)
        {
            Glyph character = Characters[index];

            if (character == null)
            {
                return;
            }

            if (Kerning != null)
            {
                left += Kerning[index] * FontSize;
            }

            if (character.Space)
            {
                left += SpaceSize + LetterSpacing;
                return;
            }

            float y = top + Ascender - ((character.Height + character.MinY) * FontSize);

            AtlasLocation locatedAt = character.Location;

            if (locatedAt == null)
            {
                // Not in font.
                return;
            }

            screenRegion.Set(left + (character.LeftSideBearing * FontSize), y, locatedAt.Width * ScaleFactor, locatedAt.Height * ScaleFactor);

            if (screenRegion.Overlaps(renderer.ClippingBoundary))
            {
                // True if this character is visible.

                // Ensure correct batch:
                SetupBatch(null, locatedAt.Atlas);

                MeshBlock block = Add();
                block.SetColour(FontColour);

                // And clip our meshblock to fit within boundary:
                block.ImageUV = null;
                UVBlock uvs = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, zIndex, locatedAt, block.TextUV);

                if (uvs.Shared)
                {
                    uvs = new UVBlock(uvs);
                }

                // Invert along X:
                float temp = uvs.MinX;
                uvs.MinX = uvs.MaxX;
                uvs.MaxX = temp;

                // Assign to the block:
                block.TextUV = uvs;
            }

            left += (character.AdvanceWidth * FontSize) + LetterSpacing;
        }
コード例 #32
0
        /// <summary>Draws a character and advances the pen onwards.</summary>
        private void DrawCharacter(int index, ref float left, float top, Renderman renderer, float zIndex, BoxRegion screenRegion)
        {
            Glyph character = Characters[index];

            if (character == null)
            {
                return;
            }

            if (Kerning != null)
            {
                left += Kerning[index] * FontSize;
            }

            AtlasLocation locatedAt;

            if (character.Image != null)
            {
                if (!character.Image.Loaded())
                {
                    return;
                }

                // It's an image (e.g. Emoji).
                locatedAt = RequireImage(character.Image);

                if (locatedAt == null)
                {
                    // It needs to be isolated. Big emoji image!
                    return;
                }

                if (CharacterProviders.FixHeight)
                {
                    // Set the region:
                    screenRegion.Set(left, top, locatedAt.Width, locatedAt.Height);
                }
                else
                {
                    screenRegion.Set(left, top, FontSize, FontSize);
                }

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // Ensure correct batch:
                    SetupBatch(locatedAt.Atlas, null);

                    // If the two overlap, this means it's actually visible.
                    MeshBlock block = Add();

                    // Set it's colour:
                    block.SetColour(Element.Style.Computed.ColorOverlay);

                    // And clip our meshblock to fit within boundary:
                    block.TextUV  = null;
                    block.ImageUV = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, zIndex, locatedAt, block.ImageUV);
                }

                left += (character.AdvanceWidth) + LetterSpacing;
                return;
            }
            else if (character.Space)
            {
                left += SpaceSize + LetterSpacing;
                return;
            }


            locatedAt = character.Location;

            if (locatedAt == null)
            {
                // Not in font.
                return;
            }

            float y = top + Ascender - ((character.Height + character.MinY) * FontSize);

            screenRegion.Set(left + (character.LeftSideBearing * FontSize), y, locatedAt.Width * ScaleFactor, locatedAt.Height * ScaleFactor);

            if (screenRegion.Overlaps(renderer.ClippingBoundary))
            {
                // True if this character is visible.

                // Ensure correct batch:
                SetupBatch(null, locatedAt.Atlas);

                MeshBlock block = Add();
                block.SetColour(FontColour);

                // And clip our meshblock to fit within boundary:
                block.ImageUV = null;
                block.TextUV  = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, zIndex, locatedAt, block.TextUV);
            }

            left += (character.AdvanceWidth * FontSize) + LetterSpacing;
        }
コード例 #33
0
ファイル: RoundCorner.cs プロジェクト: ru-ace/spark
        /// <summary>Renders the inverse of this corner for the border.</summary>
        public void RenderInverse(LayoutBox box, Renderman renderer, float cornerX, float cornerY)
        {
            float scale = RoundCorners.Computed.RenderData.ValueScale;

            if (scale != ValueScale)
            {
                // Value scale has changed - reset the radius:
                Radius     = Radius * scale / ValueScale;
                ValueScale = scale;
            }

            if (OuterArc == null)
            {
                RecomputeArcs(box.Border);
            }
            else if (InnerArc == null)
            {
                RecomputeInnerArc(box.Border);
            }

            // Get the z-Index:
            float zIndex = RoundCorners.Computed.MaxZIndex + 0.004f;

            // Grab the size of the outer arc array:
            int arcSize = OuterArc.Length;

            int currentIndex = 0;

            // Resolve the corner:
            Vector3 corner = renderer.PixelToWorldUnit(cornerX, cornerY, zIndex);

            // Ensure a batch is available:
            renderer.SetupBatch(InverseBorder, null, null);

            // For each inverse block:
            for (int i = 0; i < InverseBlocksRequired; i++)
            {
                // Get a block:
                MeshBlock block = InverseBorder.Add(renderer);

                // Set the clear colour:
                block.SetColour(Color.clear);

                // Always going to be space to sample two. Sample the first:
                Vector2 outerPoint = InnerArc[currentIndex];

                // Apply the triangle:
                block.VertexTopRight = corner;

                // Apply the first:
                block.VertexTopLeft = renderer.PixelToWorldUnit(cornerX + outerPoint.x, cornerY + outerPoint.y, zIndex);

                // Sample the second:
                outerPoint = InnerArc[currentIndex + 1];

                // Apply the second:
                block.VertexBottomLeft = renderer.PixelToWorldUnit(cornerX + outerPoint.x, cornerY + outerPoint.y, zIndex);

                if ((currentIndex + 2) >= arcSize)
                {
                    // Match the previous vertex:
                    block.VertexBottomRight = block.VertexBottomLeft;
                }
                else
                {
                    // Grab the next point along:
                    outerPoint = InnerArc[currentIndex + 2];

                    // Resolve and apply the third:
                    block.VertexBottomRight = renderer.PixelToWorldUnit(cornerX + outerPoint.x, cornerY + outerPoint.y, zIndex);
                }

                block.Done(renderer.Transform);

                // Move index along:
                currentIndex += 2;
            }
        }
コード例 #34
0
        /// <summary>Draws a character and advances the pen onwards.</summary>
        protected virtual void DrawCharacter(ref float left, Renderman renderer)
        {
            BoxRegion screenRegion = renderer.CurrentRegion;
            Color     fontColour   = renderer.FontColour;
            float     top          = renderer.TopOffset;
            int       index        = renderer.CharacterIndex;

            Glyph character = Text.Characters[index];

            if (character == null)
            {
                return;
            }

            if (Text.Kerning != null)
            {
                left += Text.Kerning[index] * Text.FontSize;
            }

            AtlasLocation locatedAt;

            if (character.Image != null)
            {
                DrawEmoji(character, ref left, renderer);
                return;
            }

            // Get atlas location:
            locatedAt = character.Location;

            // Does this character have a visual glyph? E.g. a space does not.
            if (locatedAt != null)
            {
                float y = top + renderer.TextAscender - ((character.Height + character.MinY) * Text.FontSize);

                float scaleFactor = renderer.TextScaleFactor;

                screenRegion.Set(left + (character.LeftSideBearing * Text.FontSize), y, locatedAt.Width * scaleFactor, locatedAt.Height * scaleFactor);

                if (screenRegion.Overlaps(renderer.ClippingBoundary))
                {
                    // True if this character is visible.

                    // Ensure correct batch:
                    renderer.SetupBatch(this, null, locatedAt.Atlas);

                    MeshBlock block = Add(renderer);
                    block.SetColour(fontColour);
                    block.ApplyOutline();

                    // And clip our meshblock to fit within boundary:
                    block.ImageUV = null;
                    block.TextUV  = block.SetClipped(renderer.ClippingBoundary, screenRegion, renderer, RenderData.computedStyle.ZIndex, locatedAt, block.TextUV);

                    block.Done(renderer.Transform);
                }
            }

            left += (character.AdvanceWidth * Text.FontSize) + Text.LetterSpacing;

            if (character.Charcode == (int)' ')
            {
                left += Text.WordSpacing;
            }
        }