IGUIElement clippingrect change

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

IGUIElement clippingrect change

Post by Seven »

I have created a nice windowing system that detects when IGUIElement children are outside of the parents clientrect. If this is detected, the window creates scrollbars and allows the user to 'move' the client area to view the entire child element. this all works well.

unfortunately, the children are clipped against the absolute rect of the parent, which allows them to be in the 'titlebar' area of the window.

what I need is the ability to change the child's clipping rectangle prior to it being rendered. unfortunately, the clip rect is a protected variable and I cannot have access to it from the parent.

short of changing the IGUIElement interface and adding a setClippingRect() type function, is there a way to manipulate the clipping rect from the instance of the parent?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: IGUIElement clippingrect change

Post by CuteAlien »

I fear it is as you have found out already. You could maybe add another element in between that has the size of your client area.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

any chance of getting a setClippingRect(rect<s32>) to the engine?

I can easily modify my copy so it isnt critical, but the windowing system I have is pretty sweet if I do say so myself :)

I use a 'father knows best' approach for the layout, cascading from the topmost window (the Desktop) down through the children, each of them arranging their children to fit as desired.
minimizing, maximizing, docking are complete.
the next step is resizing. I have it working on another testbed, but need to integrate it into this testbed.

for example

Code: Select all

 
 
        // create the top level window
        // the desktop class auto includes a CSGUI_Minimizebar that handles minimizing windows correctly
    Desktop = new CSGUI_Desktop(device, env, ID_DESKTOP);
 
        // create a new window that has a vertical / horiz scrollbar and is docked to the left side of its parent
        // the sysmenu flag auto creates a CSGUI_SysToolbar that houses the close, min, max, restore buttons
        // the system will handle minimizing, maximizing and restoring this window   
    CSGUI_Window* w1 = new CSGUI_Window(Desktop, env, Desktop, ID_WINDOW1, rect<s32>(100, 100, 400, 600), CS_HSCROLLBAR | CS_VSCROLLBAR | CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU, CSGUI_Layout(layoutStyle::LEFTFILL));
       
        // add it to the desktop
    Desktop->addCSChild(w1);
 
                // add a regular gui element. since the w1 window has scrollbars, the client rect can be scrolled to move the button around relatively
        env->addButton(rect<s32>(100, 10, 200, 200), w1, -1, L"testing");
 
        // add another window that is docked to the left side of its parent (in this case w1 above)
    CSGUI_Window* w2 = new CSGUI_Window(w1, env, w1, ID_WINDOW2, rect<s32>(0, 0, 100, 100), CS_VISIBLE | CS_CAPTION | CS_BORDER , CSGUI_Layout(layoutStyle::LEFTFILL));
    w1->addCSChild(w2);
                // add a toolbar to it
        CSGUI_Toolbar* w3 = new CSGUI_Toolbar(w2,ID_WINDOW3);
        w2->addCSChild(w3);
                       // here we can add guielements to the toolbar as desired
                       // toolbar guielement notifications are sent to w2 since it is the parent of the toolbar
        
        // add a window that is docked to the right hand side of the desktop      
    CSGUI_Window* w4 = new CSGUI_Window(Desktop, env, Desktop, ID_WINDOW4, rect<s32>(100, 100, 400, 600), CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU, CSGUI_Layout(layoutStyle::RIGHTFILL));
    Desktop->addCSChild(w4);
 
       // add a window that fills in the remainder of the desktop client area after all of the docked windows layouts are complete
       // in a real app, this would be a CSGUI_LevelViewer instance to render the smgr etc....
    CSGUI_Window* w5 = new CSGUI_Window(Desktop, env, Desktop, ID_WINDOW4, rect<s32>(100, 100, 100, 0), CS_VISIBLE | CS_CAPTION | CS_BORDER, CSGUI_Layout(layoutStyle::REST));
    Desktop->addCSChild(w5);
 
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

added sizing :)

if i figure out how to redo my github upload i will post the demo.

I made the mistake of adding all files to my git repository. now it wont upload because one of the files is too large.
I deleted the file and tried again, but it still wants that file.
can someone tell me how to undo this?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: IGUIElement clippingrect change

Post by CuteAlien »

Can't help with git. And don't know right now about clipping, would have to check first how that is used in all the elements and can be changed without trouble. Unfortunately I can't work on Irrlicht for the next few weeks (at least next 6 weeks).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

small video showing current gui status......


http://youtu.be/_G26-is99mo
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: IGUIElement clippingrect change

Post by CuteAlien »

Cool stuff :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

one more then back to programming

http://youtu.be/GvRzwZcavKw
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

a little tester for the gui system.

*** directory structure is the same as irrlicht so use your own media folder that is two levels up from the exe ***
i dont do any checks for loading the test scene, so it looks for normal irrlicht bin directory at ../../media
it will crash if it doesnt find it :(

uses a VERY slightly modified irrlicht.dll (only exposed clippingRect so I could clip against scrollbars)

includes: resizing, minimizing, maximizing, restoring and embedding irrlicht gui elements
also detects mouse hovering resizable window and modifies color to indicate that the window is resizable in that direction
examples :
LEFTFILL windows can be resized to the right only
TOPFILL windows can resize at bottom etc....

CSGUIToolbars cannot be resized
CSGUISysMenu toolbar is derived from CSGUIToolbar and houses min, max buttons


allows user to 'move' clientarea around so that irrlicht guielements can be fully seen.
window #1 is an example of this. use scrollbars OR click and drag mouse in clientarea to see what it does.


theory :
Desktop is top level window and cascades down through children
uses a 'father knows best' approach for child window layouts
example: CS_LAYOUT_STYLE :: LEFTFILL will put the child at the left side of the parent and resize it to fill the parent clientRect to the bottom
example: CS_LAYOUT_STYLE :: RIGHTFILL will put the child at the right side of the parent and resize it to fill the parent clientRect to the bottom

as father lays out children, it keeps track of remaining clientrect and uses it for next child so....
if LEFTFILL then father clientrect is reduced
then the toolbar (TOPFILL) will start at child.lowerrightcorner.X and extend to end of clientrect


all windows use flags for creation :
CS_VISIBLE | CS_THICKFRAME | CS_BORDER | CS_SYSMENU | CS_TRANSPARENT
creates a visible, resizable, bordered window with a CSGUI_SysMenu toolbar (close, min, max, restore) and will prevent rendering the clientarea (transparent)

added CSGUI_Window_Viewer to show how a transparent clientArea allows us to render the smgr into a window.
right click mouse to toggle camera input enabled / disabled

anyhow, I will release the source once I get it cleaned up, but wanted feedback if anyone tries it out.........

http://www.filedropper.com/csguitester
Seven
Posts: 1034
Joined: Mon Nov 14, 2005 2:03 pm

Re: IGUIElement clippingrect change

Post by Seven »

in reference to the download above......

code showing the createGui() function in tester3.cpp (create a desktop and add in some test windows)

Code: Select all

 
void createGui()
{
    // create the desktop
    Desktop = new CSGUI_Desktop(device, env, ID_DESKTOP);
 
    // add a resizable, clientarea scrollable, visible, titlbarred, bordered window with a min/max/restore/close toolbar and stick it to the left side of it's parent (the desktop in this case)
    CSGUI_Window* w1 = new CSGUI_Window(Desktop, env, Desktop, ID_WINDOW1, stringw("Scroll Client Area Mouse or Scrollbars"), rect<s32>(100, 100, 400, 600), CS_THICKFRAME | CS_HSCROLLBAR | CS_VSCROLLBAR | CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU, CSGUI_Layout(layoutStyle::LEFTFILL));
    Desktop->addCSChild(w1);
        // testing the ability to modify the clientwindow after primary creation is completed
        w1->setClientWindow(new CSGUI_ClientAreaWindow(w1));
        // add a simple button that the user can scroll around in the client window
        env->addButton(rect<s32>(100, 10, 200, 200), w1->getClientWindow(), -1, L"testing");
 
    // add a visible, titlebarred, bordered and resizable window that is a child of w1 and stick it to the bottom of it's parent
    CSGUI_Window* w2 = new CSGUI_Window(w1, env, w1, ID_WINDOW2, stringw("Window #2"), rect<s32>(0, 0, 100, 100), CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_THICKFRAME, CSGUI_Layout(layoutStyle::BOTTOMFILL));
    w1->addCSChild(w2);
 
    // a simple test of adding normal irrlight guielements ( in this case a tree of the scenenodes in the smgr)
    CSGUI_SceneTree* w4 = new CSGUI_SceneTree(Desktop, env, Desktop, ID_WINDOW4, stringw("SceneTree"), rect<s32>(100, 100, 400, 600), CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU | CS_THICKFRAME, CSGUI_Layout(layoutStyle::RIGHTFILL), smgr);
    Desktop->addCSChild(w4);
 
    // add a transparent clientwindow that renders the smgr. note that it is of style REST which means it fills whatver is left of the parents clientarea
    CSGUI_Viewer* w5 = new CSGUI_Viewer(Desktop, env, Desktop, ID_WINDOW5, stringw("Scene Viewer Right Click for mouse control"), rect<s32>(100, 100, 100, 0), CS_TRANSPARENT | CS_VISIBLE | CS_CAPTION | CS_BORDER, CSGUI_Layout(layoutStyle::REST), smgr);
    Desktop->setClientWindow(w5);
 
        // add a toolbar to the smgr viewer. add some buttons to the toolbar (only the LIGHT actually does anything in this demo)
        CSGUI_Toolbar* w3 = new CSGUI_Toolbar(w5, ID_WINDOW3);
        w5->addCSChild(w3);
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, ID_LIGHT, L"Light"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button2"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button3"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button4"));
 
}
 



full test3.exe to show how device, scene, gui etc is created..........
nothing spectacular here............

Code: Select all

 
#include "stdafx.h"
#include "common.h"
#include <conio.h>
#include <ctype.h>
 
#include "CSGUI_Desktop.h"
#include "CSGUI_Toolbar.h"
#include "CSGUI_Viewer.h"
#include "CSGUI_SceneTree.h"
#include "CSGUI_ClientAreaWindow.h"
 
using namespace CS;
 
IrrlichtDevice * device;
IVideoDriver* driver;
IGUIEnvironment* env;
ISceneManager* smgr;
 
dimension2d<u32> oldScreenSize(dimension2d<u32>(0, 0));
CSGUI_Desktop* Desktop = 0;
 
#define ID_DESKTOP 777
#define ID_WINDOW1 1
#define ID_WINDOW2 2
#define ID_WINDOW3 3
#define ID_WINDOW4 4
#define ID_WINDOW5 5 
 
void createGui()
{
    Desktop = new CSGUI_Desktop(device, env, ID_DESKTOP);
 
    CSGUI_Window* w1 = new CSGUI_Window(Desktop, env, Desktop, ID_WINDOW1, stringw("Scroll Client Area Mouse or Scrollbars"), rect<s32>(100, 100, 400, 600), CS_THICKFRAME | CS_HSCROLLBAR | CS_VSCROLLBAR | CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU, CSGUI_Layout(layoutStyle::LEFTFILL));
    Desktop->addCSChild(w1);
        w1->setClientWindow(new CSGUI_ClientAreaWindow(w1));
        env->addButton(rect<s32>(100, 10, 200, 200), w1->getClientWindow(), -1, L"testing");
 
    CSGUI_Window* w2 = new CSGUI_Window(w1, env, w1, ID_WINDOW2, stringw("Window #2"), rect<s32>(0, 0, 100, 100), CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_THICKFRAME, CSGUI_Layout(layoutStyle::BOTTOMFILL));
    w1->addCSChild(w2);
 
    CSGUI_SceneTree* w4 = new CSGUI_SceneTree(Desktop, env, Desktop, ID_WINDOW4, stringw("SceneTree"), rect<s32>(100, 100, 400, 600), CS_VISIBLE | CS_CAPTION | CS_BORDER | CS_SYSMENU | CS_THICKFRAME, CSGUI_Layout(layoutStyle::RIGHTFILL), smgr);
    Desktop->addCSChild(w4);
 
    CSGUI_Viewer* w5 = new CSGUI_Viewer(Desktop, env, Desktop, ID_WINDOW5, stringw("Scene Viewer Right Click for mouse control"), rect<s32>(100, 100, 100, 0), CS_TRANSPARENT | CS_VISIBLE | CS_CAPTION | CS_BORDER, CSGUI_Layout(layoutStyle::REST), smgr);
    Desktop->setClientWindow(w5);
 
        CSGUI_Toolbar* w3 = new CSGUI_Toolbar(w5, ID_WINDOW3);
        w5->addCSChild(w3);
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, ID_LIGHT, L"Light"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button2"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button3"));
            w3->addButton(env->addButton(rect<s32>(0, 0, 64, 16), w3, -1, L"Button4"));
 
}
 
void createScene()
{
    smgr->getRootSceneNode()->setName("RootNode");
    scene::IAnimatedMesh* mesh = smgr->getMesh("../../media/room.3ds");
 
    smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f);
 
    scene::ISceneNode* node = 0;
 
    node = smgr->addAnimatedMeshSceneNode(mesh);
    node->setName("Room");
    node->setMaterialTexture(0, driver->getTexture("../../media/wall.jpg"));
    node->getMaterial(0).SpecularColor.set(0, 0, 0, 0);
    mesh = smgr->addHillPlaneMesh("myHill",
        core::dimension2d<f32>(20, 20),
        core::dimension2d<u32>(40, 40), 0, 0,
        core::dimension2d<f32>(0, 0),
        core::dimension2d<f32>(10, 10));
 
    node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f);
    node->setPosition(core::vector3df(0, 7, 0));
 
    node->setMaterialTexture(0, driver->getTexture("../../media/stones.jpg"));
    node->setMaterialTexture(1, driver->getTexture("../../media/water.jpg"));
 
    node->setMaterialType(video::EMT_REFLECTION_2_LAYER);
    node->setName("Water");
 
    // create light
 
    node = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0),
        video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 800.0f);
    scene::ISceneNodeAnimator* anim = 0;
    anim = smgr->createFlyCircleAnimator(core::vector3df(0, 150, 0), 250.0f);
    node->addAnimator(anim);
    anim->drop();
    node->setName("Light");
 
    // attach billboard to light
 
    node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50));
    node->setMaterialFlag(video::EMF_LIGHTING, false);
    node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
    node->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));
    node->setName("Light Billboard");
    // create a particle system
 
    scene::IParticleSystemSceneNode* ps =
        smgr->addParticleSystemSceneNode(false);
 
    ps->setName("Particle System");
 
    scene::IParticleEmitter* em = ps->createBoxEmitter(
        core::aabbox3d<f32>(-7, 0, -7, 7, 1, 7), // emitter size
        core::vector3df(0.0f, 0.06f, 0.0f),   // initial direction
        80, 100,                             // emit rate
        video::SColor(0, 255, 255, 255),       // darkest color
        video::SColor(0, 255, 255, 255),       // brightest color
        800, 2000, 0,                         // min and max age, angle
        core::dimension2df(10.f, 10.f),         // min size
        core::dimension2df(20.f, 20.f));        // max size
 
    ps->setEmitter(em); // this grabs the emitter
    em->drop(); // so we can drop it here without deleting it
 
    scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
 
    ps->addAffector(paf); // same goes for the affector
    paf->drop();
 
    ps->setPosition(core::vector3df(-70, 60, 40));
    ps->setScale(core::vector3df(2, 2, 2));
    ps->setMaterialFlag(video::EMF_LIGHTING, false);
    ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
    ps->setMaterialTexture(0, driver->getTexture("../../media/fire.bmp"));
    ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
 
    scene::IVolumeLightSceneNode * n = smgr->addVolumeLightSceneNode(0, -1,
        32,                              // Subdivisions on U axis
        32,                              // Subdivisions on V axis
        video::SColor(0, 255, 255, 255), // foot color
        video::SColor(0, 0, 0, 0));      // tail color
 
    if (n)
    {
        n->setName("Volume Light");
 
        n->setScale(core::vector3df(56.0f, 56.0f, 56.0f));
        n->setPosition(core::vector3df(-120, 50, 40));
 
        // load textures for animation
        core::array<video::ITexture*> textures;
        for (s32 g = 7; g > 0; --g)
        {
            core::stringc tmp;
            tmp = "../../media/portal";
            tmp += g;
            tmp += ".bmp";
            video::ITexture* t = driver->getTexture(tmp.c_str());
            textures.push_back(t);
        }
 
        // create texture animator
        scene::ISceneNodeAnimator* glow = smgr->createTextureAnimator(textures, 150);
 
        // add the animator
        n->addAnimator(glow);
 
        // drop the animator because it was created with a create() function
        glow->drop();
    }
    // add animated character
 
    mesh = smgr->getMesh("../../media/dwarf.x");
    scene::IAnimatedMeshSceneNode* anode = 0;
 
    anode = smgr->addAnimatedMeshSceneNode(mesh);
    anode->setPosition(core::vector3df(-50, 20, -60));
    anode->setAnimationSpeed(15);
 
    // add shadow
    anode->addShadowVolumeSceneNode();
    smgr->setShadowColor(video::SColor(150, 0, 0, 0));
 
    // make the model a little bit bigger and normalize its normals
    // because of the scaling, for correct lighting
    anode->setScale(core::vector3df(2, 2, 2));
    anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true); 
    anode->setName("Dwarf");
}
 
class MyEventReceiver : public IEventReceiver
{
public:
    MyEventReceiver() : IEventReceiver() { }
 
    virtual bool OnEvent(const SEvent& event)
    {
        return false;
    }
};
 
int main()
{
    // create device and exit if creation failed
    device = createDevice(EDT_DIRECT3D9, core::dimension2d<u32>(1024, 768));
 
    // could not create selected driver.
    if (device == 0) return 1;
 
    /* The creation was successful, now we set the event receiver and
    store pointers to the driver and to the gui environment. */
    device->setWindowCaption(L"Irrlicht Engine - User Interface Demo");
    device->setResizable(true);
 
    driver = device->getVideoDriver();
    env = device->getGUIEnvironment();
    smgr = device->getSceneManager();
 
    IGUISkin* skin = env->getSkin();
    IGUIFont* font = env->getFont("media/fonthaettenschweiler.bmp");
    if (font) skin->setFont(font);
    skin->setFont(env->getBuiltInFont(), EGDF_TOOLTIP);
 
    // Then create the event receiver, giving it that context structure.
    MyEventReceiver receiver;
 
    // And tell the device to use our custom event receiver.
//  device->setEventReceiver(&receiver);
 
    createGui();
 
    createScene();
 
    while (device->run() && driver)
    {
        if (device->isWindowActive())
        {
            if (driver->getScreenSize() != oldScreenSize)
            {
                if (Desktop) Desktop->onSize(rect<s32>(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height));
                oldScreenSize = driver->getScreenSize();
            }
 
            driver->beginScene(true, true);
            //smgr->drawAll();
            env->drawAll();
            driver->endScene();
        }
    }
    device->drop();
 
    return 0;
}
 
 
Post Reply