Blink Label

classic Classic list List threaded Threaded
3 messages Options
marcoma9023 marcoma9023
Reply | Threaded
Open this post in threaded view
|

Blink Label

Hi,

I need to make labelNode, FeatureNode (of Feature, or LineString) blinking.

Do you have any ideas?
Blanky Blanky
Reply | Threaded
Open this post in threaded view
|

Re: Blink Label

This post was updated on .
This isn't really an osgEarth question, so much as an osg question. What you can do is install a cull callback on the node and in your derived callback do some boolean logic of which you use to determine if the node should be traversed or not. A FeatureNode inherits from osg::Group, so all traversal rules apply to it from the osgViewer::Viewer and its osg::Camera's perspective.

You'll need to both make a new class that includes and inherits from osg::NodeCallback and then override the following function of osg::NodeCallback:

void operator()(osg::Node* node, osg::NodeVisitor* nv) override;

In the body of the operator() function, you'll need to essentially do something along the lines of using an osg userValue (which is a glorified std::string to some type T value map):

void BlinkingCallback::operator()(osg::Node* node, osg::NodeVisitor* nv){

    bool isBlinking(false);
    bool blinkingState(false);      //Assume false == invisible, true == visible
    int  lastTimeStateChanged(0); //float if you need milliseconds, otherwise an int would suffice
    int  blinkingInterval(0);     //Assume 500 milliseconds

    //User values populate variables via reference, rather than a return value
    node->getUserValue("isBlinking",           isBlinking);
    node->getUserValue("blinkingState",        blinkingState); //Toggles on and off state between traversals
    node->getUserValue("lastTimeStateChanged", lastTimeStateChanged);
    node->getUserValue("blinkingInterval",     blinkingInterval);

    //Assume we should by default be rendering based on the previous state
    bool shouldTraverse(blinkingState);

    //If it is actually blinking, we should determine if it should be in a visible or invisible state
    if(isBlinking){

        int curTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // Windows or Linux solution

        if(abs(lastTimeStateChanged - curTime) >= blinkingInterval){

            shouldTraverse = !blinkingState; //Toggle the state to the inverse of the current one
            node->setUserValue("lastTimeStateChanged", curTime); //Now we mark the current interval as the last time the state changed
            node->setUserValue("blinkingState", !blinkingState); //Invert the state so the next time this boolean logic gets in here we're in the inverse state

        }

    }

    //Determination to traverse should've been done in the above logic, if needed
    if(shouldTraverse){

        traverse(node, nv);

    }
    //else we don't render the node
   
}

Then on your FeatureNode instance you need to install a cullCallback like this of your new callback type:

featureNode->setCullCallback(new CustomBlinkingCallback());
featureNode->setUserValue("isBlinking", true);
featureNode->setUserValue("blinkingInterval", 500);
//The other user values will default to false for bool, 0 for int

//Now it should toggle it's visibility every half a second when added to your scene graph hopefully
//Note: I have compiled and ran this code and tested it in a simple scene graph and confirmed it works properly
marcoma9023 marcoma9023
Reply | Threaded
Open this post in threaded view
|

Re: Blink Label

Thanks.

I'll try it now