Panel.cs :  » Game » RealmForge » Axiom » Overlays » Elements » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Game » RealmForge 
RealmForge » Axiom » Overlays » Elements » Panel.cs
#region LGPL License
/*
Axiom Game Engine Library
Copyright (C) 2003  Axiom Project Team

The overall design, and a majority of the core engine and rendering code 
contained within this library is a derivative of the open source Object Oriented 
Graphics Engine OGRE, which can be found at http://ogre.sourceforge.net.  
Many thanks to the OGRE team for maintaining such a high quality project.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#endregion

using System;
using System.Diagnostics;
using Axiom.Configuration;
using Axiom.Core;
using Axiom.Scripting;
using Axiom.Graphics;

namespace Axiom.Overlays.Elements{
  /// <summary>
  ///   GuiElement representing a flat, single-material (or transparent) panel which can contain other elements.
  /// </summary>
  /// <remarks>
  ///   This class subclasses GuiContainer because it can contain other elements. Like other
  ///   containers, if hidden it's contents are also hidden, if moved it's contents also move etc. 
  ///   The panel itself is a 2D rectangle which is either completely transparent, or is rendered 
  ///   with a single material. The texture(s) on the panel can be tiled depending on your requirements.
  ///   <p/>
  ///   This component is suitable for backgrounds and grouping other elements. Note that because
  ///   it has a single repeating material it cannot have a discrete border (unless the texture has one and
  ///   the texture is tiled only once). For a bordered panel, see it's subclass BorderPanel.
  ///   <p/>
  ///   Note that the material can have all the usual effects applied to it like multiple texture
  ///   layers, scrolling / animated textures etc. For multiple texture layers, you have to set 
  ///   the tiling level for each layer.
  /// </remarks>
  public class Panel : OverlayElementContainer {
    #region Member variables
    
        protected float[] tileX = new float[Config.MaxTextureLayers];
        protected float[] tileY = new float[Config.MaxTextureLayers];
        protected bool isTransparent;
        protected int numTexCoords;
        protected RenderOperation renderOp = new RenderOperation();

        // source bindings for vertex buffers
        const int POSITION = 0;
        const int TEXTURE_COORDS = 1;

    #endregion
    
    #region Constructors
    
    internal Panel(string name) : base(name) {
            // initialize the default tiling to 1 for all layers
            for(int i = 0; i < Config.MaxTextureLayers; i++) {
                tileX[i] = 1.0f;
                tileY[i] = 1.0f;
            }
    }
    
    #endregion
    
    #region Methods
    
        /// <summary>
        ///    Returns the geometry to use during rendering.
        /// </summary>
        /// <param name="op"></param>
        public override void GetRenderOperation(Axiom.Graphics.RenderOperation op) {
            op.vertexData = renderOp.vertexData;
            op.operationType = renderOp.operationType;
            op.useIndices = renderOp.useIndices;
        }

        /// <summary>
        /// 
        /// </summary>
        public override void Initialize() {
            // setup the vertex data
            renderOp.vertexData = new VertexData();

            // Vertex declaration: 1 position, add texcoords later depending on #layers
            // Create as separate buffers so we can lock & discard separately
            VertexDeclaration decl = renderOp.vertexData.vertexDeclaration;
            decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position);
            renderOp.vertexData.vertexStart = 0;
            renderOp.vertexData.vertexCount = 4;
            
            // create the first vertex buffer, mostly static except during resizing
            HardwareVertexBuffer buffer =
                HardwareBufferManager.Instance.CreateVertexBuffer(
                     decl.GetVertexSize(POSITION),
                     renderOp.vertexData.vertexCount,
                     BufferUsage.StaticWriteOnly);

            // bind the vertex buffer
            renderOp.vertexData.vertexBufferBinding.SetBinding(POSITION, buffer);

            // no indices, and issue as a tri strip
            renderOp.useIndices = false;
            renderOp.operationType = OperationType.TriangleStrip;
        }

        /// <summary>
        ///    
        /// </summary>
        /// <param name="tileX"></param>
        /// <param name="tileY"></param>
        /// <param name="layer"></param>
        public void SetTiling(float x, float y, int layer) {
            Debug.Assert(layer < Config.MaxTextureLayers, "layer < Config.MaxTextureLayers");
            Debug.Assert(x != 0 && y != 0, "tileX != 0 && tileY != 0");

            tileX[layer] = x;
            tileY[layer] = y;

            UpdateTextureGeometry();
        }

        /// <summary>
        ///    Internal method for setting up geometry, called by GuiElement.Update
        /// </summary>
        protected override void UpdatePositionGeometry() {
            /*
                0-----2
                |    /|
                |  /  |
                |/    |
                1-----3
            */
            float left, right, top, bottom;
            left = right = top = bottom = 0.0f;

            /* Convert positions into -1, 1 coordinate space (homogenous clip space).
                - Left / right is simple range conversion
                - Top / bottom also need inverting since y is upside down - this means
                  that top will end up greater than bottom and when computing texture
                  coordinates, we have to flip the v-axis (ie. subtract the value from
                  1.0 to get the actual correct value).
            */

            left = this.DerivedLeft * 2 - 1;
            right = left + (width * 2);
            top = -((this.DerivedTop * 2) - 1);
            bottom = top - (height * 2);

            // get a reference to the position buffer
            HardwareVertexBuffer buffer =
                renderOp.vertexData.vertexBufferBinding.GetBuffer(POSITION);

            // lock the buffer
            IntPtr data = buffer.Lock(BufferLocking.Discard);
            int index = 0;

            // modify the position data
            unsafe {
                float* posPtr = (float*)data.ToPointer();

                posPtr[index++] = left;
                posPtr[index++] = top;
                posPtr[index++] = -1;

                posPtr[index++] = left;
                posPtr[index++] = bottom;
                posPtr[index++] = -1;

                posPtr[index++] = right;
                posPtr[index++] = top;
                posPtr[index++] = -1;

                posPtr[index++] = right;
                posPtr[index++] = bottom;
                posPtr[index++] = -1;
            }

            // unlock the position buffer
            buffer.Unlock();
        }

        public override void UpdateRenderQueue(RenderQueue queue) {
            if(isVisible) {
                // only add this panel to the render queue if it is not transparent
                // that would mean the panel should be a virtual container of sorts,
                // and the children would still be rendered
                if(!isTransparent && material != null) {
                    base.UpdateRenderQueue (queue);
                }

                for(int i = 0; i < childList.Count; i++) {
                    ((OverlayElement)childList[i]).UpdateRenderQueue(queue);
                }
            }
        }


        /// <summary>
        ///    Called to update the texture coords when layers change.
        /// </summary>
        protected virtual void UpdateTextureGeometry() {
            if(material != null) {
                int numLayers = material.GetTechnique(0).GetPass(0).NumTextureUnitStages;

                VertexDeclaration decl = renderOp.vertexData.vertexDeclaration;

                // if the required layers is less than the current amount of tex coord buffers, remove
                // the extraneous buffers
                if(numTexCoords > numLayers) {
                    for(int i = numTexCoords; i > numLayers; --i) {
                        // TODO: Implement RemoveElement
                        //decl.RemoveElement(TEXTURE_COORDS, i);
                    }
                }
                else if(numTexCoords < numLayers) {
                    // we need to add more buffers
                    int offset = VertexElement.GetTypeSize(VertexElementType.Float2) * numTexCoords;

                    for(int i = numTexCoords; i < numLayers; i++) {
                        decl.AddElement(TEXTURE_COORDS, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i);
                        offset += VertexElement.GetTypeSize(VertexElementType.Float2);
                    } // for
                } // if

                // if the number of layers changed at all, we'll need to reallocate buffer
                if(numTexCoords != numLayers) {
                    HardwareVertexBuffer newBuffer =
                        HardwareBufferManager.Instance.CreateVertexBuffer(
                            decl.GetVertexSize(TEXTURE_COORDS),
                            renderOp.vertexData.vertexCount,
                            BufferUsage.StaticWriteOnly);

                    // Bind buffer, note this will unbind the old one and destroy the buffer it had
                    renderOp.vertexData.vertexBufferBinding.SetBinding(TEXTURE_COORDS, newBuffer);

                    // record the current number of tex layers now
                    numTexCoords = numLayers;
                } // if

                // get the tex coord buffer
                HardwareVertexBuffer buffer = renderOp.vertexData.vertexBufferBinding.GetBuffer(TEXTURE_COORDS);
                IntPtr data = buffer.Lock(BufferLocking.Discard);

                unsafe {

                    float* texPtr = (float*)data.ToPointer();
                    int texIndex = 0;

                    int uvSize = VertexElement.GetTypeSize(VertexElementType.Float2) / sizeof(float);
                    int vertexSize = decl.GetVertexSize(TEXTURE_COORDS) / sizeof(float);

                    for(int i = 0; i < numLayers; i++) {
                        // Calc upper tex coords
                        float upperX = 1.0f * tileX[i];
                        float upperY = 1.0f * tileY[i];
                
                        /*
                            0-----2
                            |    /|
                            |  /  |
                            |/    |
                            1-----3
                        */
                        // Find start offset for this set
                        texIndex = (i * uvSize);

                        texPtr[texIndex] = 0.0f;
                        texPtr[texIndex + 1] = 0.0f;

                        texIndex += vertexSize; // jump by 1 vertex stride
                        texPtr[texIndex] = 0.0f;
                        texPtr[texIndex + 1] = upperY;

                        texIndex += vertexSize;
                        texPtr[texIndex] = upperX;
                        texPtr[texIndex + 1] = 0.0f;

                        texIndex += vertexSize;
                        texPtr[texIndex] = upperX;
                        texPtr[texIndex + 1] = upperY;
                    } // for
                } // unsafev

                // unlock the buffer
                buffer.Unlock();
            } // if material != null
        }

    #endregion
    
    #region Properties
    
        /// <summary>
        /// 
        /// </summary>
        public bool IsTransparent {
            get {
                return isTransparent;
            }
            set {
                isTransparent = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public override string MaterialName {
            set {
                base.MaterialName = value;
                UpdateTextureGeometry();
            }
            get {
                return base.MaterialName;
            }
        }

    #endregion

        #region Script parser methods

        [AttributeParser("tiling", "Panel")]
        public static void ParseTiling(string[] parms, params object[] objects) {
            Panel panel = (Panel)objects[0];

            panel.SetTiling(StringConverter.ParseFloat(parms[0]), StringConverter.ParseFloat(parms[1]), int.Parse(parms[2]));
        }

        [AttributeParser("transparent", "Panel")]
        public static void ParseTransparent(string[] parms, params object[] objects) {
            Panel panel = (Panel)objects[0];

            panel.IsTransparent = bool.Parse(parms[0]);
        }

        #endregion Script parser methods

  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.