天天看点

osgEarth示例分析——osgearth_controls前言运行效果结构分析代码分析

前言

本示例演示osgearth_controls示例,包括各种控件的添加以及简单的事件相应。

像小房子一样的图片,是替换了源码中个gif图。不知为何gif图总是加载不上。

执行程序

// 依然沿用之前的earth文件
osgearth_controlsd.exe earth_image\china-simple.earth
           

滑动红色进度条,对应的会显示百分比。

选中checkbox 1,会打印输入选中情况。

滑动蓝色进度条,粉色房子会旋转。

点击4个标签,会打印输出点击标签上位置xy信息。

运行效果

osgEarth示例分析——osgearth_controls前言运行效果结构分析代码分析

结构分析

osgEarth示例分析——osgearth_controls前言运行效果结构分析代码分析

代码分析

对代码checkbox部分进行了增加,增加选中复选框时,打印输出选中状态。

#include <typeinfo>

#include <osg/Notify>
#include <osgDB/ReadFile>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include <osgEarth/Registry>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/Controls>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthSymbology/Color>

using namespace osgEarth::Symbology;
using namespace osgEarth::Util::Controls;


void createControls( ControlCanvas* );
ImageControl* s_imageControl = 0L;// 包含光栅图像的控件。全局变量


int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc,argv);       
    osgViewer::Viewer viewer(arguments);

    osg::Node* node = osgEarth::Util::MapNodeHelper().load(arguments, &viewer);
    if (!node)
    {
        OE_WARN << "No earth file on the command line." << std::endl;
        return -1;
    }
    
    osg::Group* root = new osg::Group();
    root->addChild( node );

    // create a surface to house the controls 创建曲面以放置控件,父类为osg::Camera
    ControlCanvas* cs = ControlCanvas::getOrCreate( &viewer );

    viewer.setSceneData( root );
    viewer.setCameraManipulator( new osgEarth::Util::EarthManipulator );

    // create some controls.
    createControls( cs );

    return viewer.run();
}

// 点击事件
struct MyClickHandler : public ControlEventHandler
{
	// 在什么控件上点击,并输出鼠标在控件中点击的位置
    void onClick( Control* control, const osg::Vec2f& pos, int mouseButtonMask )
    {
        OE_NOTICE << "You clicked at (" << pos.x() << ", " << pos.y() << ") within the control."
            << std::endl;
    }
};

// 仿照 MyClickHandler点击事件,写checkbox勾选事件
struct MyCheckBoxHandler : public ControlEventHandler
{
	// 在什么控件上点击,并输出鼠标在控件中点击的位置
	void onValueChanged(Control* control, bool value) 
	{
		OE_NOTICE << "You checked at " << value << std::endl;
	}
};

// 标签控件
static LabelControl* s_sliderLabel;// 全局变量

// 滑块控件
struct MySliderHandler : public ControlEventHandler
{
    void onValueChanged( Control* control, float value )
    {
        std::stringstream buf;
        buf << (int)value;
        std::string str;
        str = buf.str();
        s_sliderLabel->setText( str );// 将变化的值显示在标签上
    }
};

// 旋转图
struct RotateImage : public ControlEventHandler
{
    void onValueChanged( Control* control, float value )
    {
        if (s_imageControl)
            s_imageControl->setRotation( Angular(value) );
    }
};

void
createControls( ControlCanvas* cs )
{
    // a container centered on the screen, containing an image and a text label.
    {
        VBox* center = new VBox();
        center->setBorderColor( 1, 1, 1, 1 );// 边框白色
        center->setBackColor( .6,.5,.4,0.5 );// 填充色
        center->setPadding( 10 );		// 内边距属性
        center->setHorizAlign( Control::ALIGN_CENTER );// 水平居中
        center->setVertAlign( Control::ALIGN_CENTER ); // 垂直居中

        // Add an image:
		// gif的图加载不上
        // osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile("D:/FreeXGIS/osgearth_gch/data/osgearth.gif");
		osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile("D:/FreeXGIS/osgearth_gch/data/m2525_air.png");
        if ( image.valid() )
        {
			// s_imageControl 全局变量,可以接收到滑块的值
            s_imageControl = new ImageControl( image.get() );
            s_imageControl->setHorizAlign( Control::ALIGN_CENTER );// 图片居中
            s_imageControl->setFixSizeForRotation( true );// 支持旋转
            center->addControl( s_imageControl );
            center->setHorizAlign( Control::ALIGN_CENTER );// 水平居中(上面不是设置过了吗???)
        }

        // Add a text label:
        LabelControl* label = new LabelControl( "osgEarth Controls Toolkit" );
        label->setFont( osgEarth::Registry::instance()->getDefaultFont() );
        label->setFontSize( 24.0f );// 字号
        label->setHorizAlign( Control::ALIGN_CENTER );// 字体居中
        label->setMargin( 5 );// 边距5像素
        center->addControl( label );

        // Rotation slider
        HBox* rotateBox = new HBox();// 水平
        rotateBox->setChildVertAlign( Control::ALIGN_CENTER );// 插入HBox的控件垂直居中
        rotateBox->setHorizFill( true );// 控件水平填充
        rotateBox->setBackColor( Color::Blue );// 背景蓝色
        {
            rotateBox->addControl( new LabelControl("Rotate: ") );// 添加label控件

            HSliderControl* rotateSlider = new HSliderControl( -180.0, 180.0, 0.0 );// 滑块控件,范围[-180,180]
            rotateSlider->addEventHandler( new RotateImage() );// s_imageControl 可以接收到值
            rotateSlider->setHeight( 8.0f );// 高度
            rotateSlider->setHorizFill( true );// 控件水平填充
            rotateBox->addControl( rotateSlider );// 滑块放入旋转box中
        }
        center->addControl( rotateBox );

        cs->addControl( center );
    }

    // a simple vbox with absolute positioning in the upper left with two text labels.
    {
        VBox* ul = new VBox();// 垂直box
        ul->setPosition( 20, 20 );
        ul->setPadding( 10 );// 内边距
        {
			// 不同于上面的label控件的构造方式
            LabelControl* title = new LabelControl( "Upper left control", 22, osg::Vec4f(1,1,0,1) );
            ul->addControl( title );

            LabelControl* content = new LabelControl( "Here is some text in the upper left control" );
            ul->addControl( content );

            HBox* c2 = new HBox();// 水平box
            c2->setChildSpacing( 10 );// 子控件的间距
            {
                HSliderControl* slider = new HSliderControl( 0, 100 );
                slider->setBackColor( .6,0,0,1 );
                slider->setHeight( 25 );
                slider->setWidth( 300 );
                slider->addEventHandler( new MySliderHandler() );
                c2->addControl( slider );

                s_sliderLabel = new LabelControl();// 按理说,应该先new s_sliderLabel,再new slider.
                s_sliderLabel->setVertAlign( Control::ALIGN_CENTER );
                c2->addControl( s_sliderLabel );        
            }
            ul->addControl( c2 );

            HBox* c3 = new HBox(); // 处理两个复选框
            c3->setHorizAlign( Control::ALIGN_CENTER );
            c3->setChildSpacing( 10 );
            {
                HBox* c4 = new HBox(); // 每一个复选框,都是由一个框和一个文字组成
                c4->setChildSpacing( 5 );
                {
					// 原版并没有添加事件
                    //c4->addControl( new CheckBoxControl( true ) );
                    //c4->addControl( new LabelControl( "Checkbox 1" ) );

					// 修改获取选中状态并打印输出
					CheckBoxControl *ckbx = new CheckBoxControl(true);
					ckbx->addEventHandler(new MyCheckBoxHandler());
					c4->addControl(ckbx);
					c4->addControl(new LabelControl("Checkbox 1"));
                }
                c3->addControl( c4 );

                HBox* c5 = new HBox();
                c5->setChildSpacing( 5 );
                {
                    c5->addControl( new CheckBoxControl( false ) );
                    c5->addControl( new LabelControl( "Checkbox 2" ) );
                }
                c3->addControl( c5 );
            }
            ul->addControl( c3 );
        }
        cs->addControl( ul );

        ul->addEventHandler( new MyClickHandler );
    }

    // a centered hbox container along the bottom on the screen.
    {
        HBox* bottom = new HBox();// 底部的水平box,放了4个label
        bottom->setBackColor(0,0,0,0.5);        
        bottom->setMargin( 10 );
        bottom->setChildSpacing( 145 );
        bottom->setVertAlign( Control::ALIGN_BOTTOM );// 垂直方向,靠底部
        bottom->setHorizAlign( Control::ALIGN_CENTER );

        for( int i=0; i<4; ++i )
        {
            LabelControl* label = new LabelControl();
            std::stringstream buf;
            buf << "Label_" << i;
            std::string str;
            str = buf.str();
            label->setText( str );
            label->setMargin( 10 );
            label->setBackColor( 1,1,1,0.4 );// 背景色
            bottom->addControl( label );

            label->setActiveColor(1,.3,.3,1);
            label->addEventHandler( new MyClickHandler );
        }

        cs->addControl( bottom );
    }
}
           

继续阅读