Page 1 of 1

Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 01:02
by paperpusher
I am planning on putting a lot of images in my CEGUI application and I would like to find out two things:

1) What is the simplest structure for displaying an image using imageset/looknfeel?

Code: Select all

<?xml version="1.0" ?>
<Falagard>
<!--
***************************************************
        MyLook/staticImageOne
***************************************************
-->
<WidgetLook name="MyLook/staticImageOne">
    ???? what goes here ????
</WidgetLook>
</Falagard>

I think the scheme line would look something like this:

Code: Select all

<FalagardMapping WindowType="MyLook/staticImageOne"    TargetType="DefaultWindow"    Renderer="Falagard/Default"    LookNFeel="MyLook/staticImageOne" />


2) Is it possible to create a window dynamically that consists of a static image (maybe a jpg, gif, or png) without using an imageset/looknfeel?

Thanks in advance :wink:

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 12:03
by CrazyEddie
paperpusher wrote:1) What is the simplest structure for displaying an image using imageset/looknfeel?

Something like this, I think:

Code: Select all

<?xml version="1.0" ?>
<Falagard>
<!--
***************************************************
        MyLook/staticImageOne
***************************************************
-->
<WidgetLook name="MyLook/staticImageOne">
    <PropertyDefinition name="Image" initialValue="" redrawOnWrite="true" />
    <ImagerySection name="image">
        <ImageryComponent>
            <Area>
                <Dim type="LeftEdge" ><AbsoluteDim value="0" /></Dim>
                <Dim type="TopEdge" ><AbsoluteDim value="0" /></Dim>
                <Dim type="RightEdge" ><UnifiedDim scale="1.0" type="RightEdge" /></Dim>
                <Dim type="BottomEdge" ><UnifiedDim scale="1.0" type="BottomEdge" /></Dim>
            </Area>
            <ImageProperty name="Image" />
            <VertFormat type="Stretched" />
            <HorzFormat type="Stretched" />
        </ImageryComponent>
    </ImagerySection>
    <StateImagery name="Enabled">
        <Layer>
            <Section section="image" />
        </Layer>
    </StateImagery>
    <StateImagery name="Disabled">
        <Layer>
            <Section section="image" />
        </Layer>
    </StateImagery>
</WidgetLook>
</Falagard>


I think the scheme line would look something like this:

Code: Select all

<FalagardMapping WindowType="MyLook/staticImageOne"    TargetType="DefaultWindow"    Renderer="Falagard/Default"    LookNFeel="MyLook/staticImageOne" />

Correct.

2) Is it possible to create a window dynamically that consists of a static image (maybe a jpg, gif, or png) without using an imageset/looknfeel?

It's difficult not to use an Imageset at the moment. Though you can load an imageset directly from an image file (i.e. no supporting XML needed) via CEGUI::ImagesetManager::createFromImageFile. It might be possible to create an all new window type that does not require a WindowRenderer or LookNFeel assigned (though IIRC this somehow got messed up and somewhere along the line one or both of these items became a 'requirement', this was wrong and will be fixed - eventually) - but no built in window type can do this.

CE.

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 13:41
by paperpusher
It might be possible to create an all new window type that does not require a WindowRenderer or LookNFeel assigned

How would you do it WITH a LookNFeel Assigned, and load the image into this pre-defined window via CEGUI::ImagesetManager::createFromImageFile. I see the definition for StaticImage in TaharezLook is defined as a type DefaultWindow. Is this the intended use of this window to load images from other imagesets?
but no built in window type can do this.

Or can it only be used to load images from its own imageset?

Can you provide a small snippet on a way to produce a window with CEGUI::ImagesetManager::createFromImageFile? I don't understand how to do it.

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 14:12
by paperpusher
This is what I got to work as far as the XML definition in the LookNFeel file... Let me know if their is a way to simplify this, or If I somehow missed the point :lol:

Code: Select all

<?xml version="1.0" ?>
<Falagard>
<!--
***************************************************
        MyLook/staticImageOne
***************************************************
-->
<WidgetLook name="MyLook/staticImageOne">
    <PropertyDefinition name="Image" initialValue="" redrawOnWrite="true" />
    <ImagerySection name="image">
            <FrameComponent>
                <Area>
                    <Dim type="LeftEdge"><AbsoluteDim value="0" /></Dim>
                    <Dim type="TopEdge"><AbsoluteDim value="0" /></Dim>
                    <Dim type="Width"><UnifiedDim scale="1" type="Width" /></Dim>
                    <Dim type="Height"><UnifiedDim scale="1" type="Height" /></Dim>
                </Area>
                <Image type="Background" imageset="MyLook" image="NameOfImage" />
            </FrameComponent>
        <ImageryComponent>
            <Area>
                <Dim type="LeftEdge" ><AbsoluteDim value="0" /></Dim>
                <Dim type="TopEdge" ><AbsoluteDim value="0" /></Dim>
                <Dim type="RightEdge" ><UnifiedDim scale="1.0" type="RightEdge" /></Dim>
                <Dim type="BottomEdge" ><UnifiedDim scale="1.0" type="BottomEdge" /></Dim>
            </Area>
            <ImageProperty name="Image" />
            <VertFormat type="Stretched" />
            <HorzFormat type="Stretched" />
        </ImageryComponent>
    </ImagerySection>
    <StateImagery name="Enabled">
        <Layer>
            <Section section="image" />
        </Layer>
    </StateImagery>
    <StateImagery name="Disabled">
        <Layer>
            <Section section="image" />
        </Layer>
    </StateImagery>
</WidgetLook>
</Falagard>

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 15:59
by CrazyEddie
If you want the image permanently set and not configurable, you don't also need the second part with the configurable image. If the first image is for a background, you never said you wanted that ;) Also, for single images, you should prefer ImageryComponent over FrameComponent - there'll not be a lot of difference, but ImageryComponent has the potential to be faster.

I'll post an example of a custom window in about half an hour ;)

CE.

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 16:23
by CrazyEddie
Ok. This is the simplest example I could come up with. Basically what we do here is create a new Window type that just draws a single image over it's entire surface; there is no WindowRenderer no LookNFeel, no nothing - this is as raw as it gets ;) The window will take the name of an image file to load, it will use the same filename as the name of the imageset and will automatically load the file for you, allowing you to set the image without dealing directly with imagesets (though any created imageset does not get cleaned up until the end).

First we have to define the new Window class. This will be a basic affair with a function to set the image that's to be drawn, and an override for the function that does the drawing, and that's all:

Code: Select all

//----------------------------------------------------------------------------//
class ImageWindow : public CEGUI::Window
{
public:
    // Used by the window factory template to know the type name.
    static const CEGUI::String WidgetTypeName;

    ImageWindow(const CEGUI::String& type, const CEGUI::String& name);

    // function to set the image to be drawn.
    void setImage(const CEGUI::String& filename);

protected:
    // override from CEGUI::Window
    void populateGeometryBuffer();

    // holds ptr to image to draw.
    const CEGUI::Image* d_image;
};


Because we use the simplified template system for registering the new type, this requires we provide a member string named WidgetTypeName, so we define that:

Code: Select all

//----------------------------------------------------------------------------//
const CEGUI::String ImageWindow::WidgetTypeName("ImageWindow");


The constructor just initialises the base class and the member variable:

Code: Select all

//----------------------------------------------------------------------------//
ImageWindow::ImageWindow(const CEGUI::String& type, const CEGUI::String& name) :
    CEGUI::Window(type, name),
    d_image(0)
{
}


The setImage function creates the imageset and invalidates the window so the new image will be drawn next time around:

Code: Select all

//----------------------------------------------------------------------------//
void ImageWindow::setImage(const CEGUI::String& filename)
{
    d_image = &CEGUI::ImagesetManager::getSingleton().
        createFromImageFile(filename, filename).getImage("full_image");

    invalidate();
}


And finally, the populateGeometryBuffer call does the drawing operation. In this case it draws any image set over the entire area of the window's surface:

Code: Select all

//----------------------------------------------------------------------------//
void ImageWindow::populateGeometryBuffer()
{
    // draw the image for our entire area
    if (d_image)
        d_image->draw(*d_geometry, CEGUI::Vector2(0, 0), d_pixelSize, 0);
}


Ok. That covers the new Window type. So how do you use this?

First you have to register the new type with the system:

Code: Select all

    using namespace CEGUI;

    // Add our new window type:
    WindowFactoryManager::addFactory<TplWindowFactory<ImageWindow> >();


And that's pretty much it ;)

Now you can create an instance of the new window type:

Code: Select all

    // create an instance of ImageWindow
    ImageWindow* wnd = static_cast<ImageWindow*>(
        WindowManager::getSingleton().createWindow("ImageWindow"));


Set the image:

Code: Select all

    // set the image
    wnd->setImage("logo.png");


And set the position and size as you would normally:

Code: Select all

    // give window position and size
    wnd->setPosition(UVector2(UDim(0.25f, 0), UDim(0.25f, 0)));
    wnd->setSize(UVector2(UDim(0.5f, 0), UDim(0.5f, 0)));


Obviously there is no support for an 'Image' property, or such, you can access via XML, but that was not the point; the point was a minimal example ;)

CE

Re: Stripped down looknfeel for a simple static image

Posted: Tue Mar 23, 2010 17:49
by paperpusher
WOW!

That is EXACTLY what I wanted... thanks!

Now all I need is to be able to play movies... but that is a story for another thread....

Re: Stripped down looknfeel for a simple static image

Posted: Tue Jun 29, 2010 22:38
by Excizted
Anyone else taking use of this excellent thread, please consider using this version of populateGeometryBuffer() to allow alpha:

Code: Select all

void ImageWindow::populateGeometryBuffer()
{
    if(d_image)
        d_image->draw(*d_geometry, CEGUI::Vector2(0, 0), d_pixelSize, 0, CEGUI::ColourRect(CEGUI::colour(1.f, 1.f, 1.f, this->getAlpha())));
}

Re: Stripped down looknfeel for a simple static image

Posted: Wed Jun 30, 2010 19:25
by jacmoe
Woohoo! Great snippet! :hammer:

Is this on the wiki already? :)

Re: Stripped down looknfeel for a simple static image

Posted: Wed Jun 30, 2010 20:05
by agamemnus
Where do you actually put that function, and how do you use it?

Re: Stripped down looknfeel for a simple static image

Posted: Wed Jun 30, 2010 20:21
by Jamarr
agamemnus wrote:Where do you actually put that function, and how do you use it?

um...look 4 posts above yours.

Re: Stripped down looknfeel for a simple static image

Posted: Wed Jun 30, 2010 22:55
by agamemnus
I was hoping to use pre-existing windows... :\

Re: Stripped down looknfeel for a simple static image

Posted: Thu Jul 01, 2010 09:20
by CrazyEddie
jacmoe wrote:Woohoo! Great snippet! :hammer:

Is this on the wiki already? :)

Not at the moment, no ;)

CE.