<commit_before>/* GCE.cpp
 *
 * Created on: 06.05.2013
 * Author: cls
 */

#include "GCE.h"
#include <unordered_map>

namespace NetworKit {

GCE::GCE(const Graph& G, std::string objective) : SelectiveCommunityDetector(G), objective(objective) {
	if (G.numberOfSelfLoops() > 0) {
		throw std::runtime_error("Graphs with self-loops are not supported in GCE");
	}
}

std::map<node, std::set<node> >  GCE::run(std::set<unsigned int>& seeds) {
    std::map<node, std::set<node> > result;
    for (auto seed : seeds) {
        result[seed] = expandSeed(seed);
    }
    return result;
}

std::set<node> GCE::expandSeed(node s) {
    /**
    * Check if set contains node.
    */
	auto in = [](const std::set<node>& A, node x) {
		return (A.find(x) != A.end());
	};

	std::set<node> community;

	// values per community
	double intWeight = 0;
    double extWeight = 0;

	struct node_property_t {
		double degInt;
		double degExt;
	};

	std::unordered_map<node, node_property_t> currentShell;

	G.forNeighborsOf(s, [&](node, node u, edgeweight ew) {
		currentShell.insert(std::make_pair(u, node_property_t {.degInt =  ew, .degExt = G.weightedDegree(u) - ew}));
		extWeight += ew;
	});

    double currentQ = 0.0; // current community quality

    auto boundary = [&](const std::set<node>& C) {
		std::set<node> sh;
		for (const auto &s : currentShell) {
			G.forNeighborsOf(s.first, [&](node u){
				if (!in(C, u)) {
					sh.insert(s.first);
				}
			});
		}
		return sh;
	};

#ifndef NDEBUG
	/**
	 * internal and external weighted degree of a node with respect to the community
	 */
	auto intExtDeg = [&](node v, const std::set<node>& C) {
		double degInt = 0;
		double degExt = 0;
		G.forNeighborsOf(v, [&](node, node u, edgeweight ew) {
			if (in(C, u)) {
				degInt += ew;
			} else {
				degExt += ew;
			}
		});
		return std::make_pair(degInt, degExt);
	};

    auto intExtWeight = [&](const std::set<node>& community) {
        double internal = 0;
        double external = 0;
        for (node u : community) {
            G.forEdgesOf(u, [&](node, node v, edgeweight ew) {
                if (in(community, v)) {
                    internal += ew;
                } else {
                    external += ew;
                }
            });
        }
        internal = internal / 2;    // internal edges were counted twice
        return std::make_pair(internal, external);
    };
#endif

    /*
     * objective function M
     * @return quality difference for the move of v to C
     */
	auto deltaM = [&](node, double degInt, double degExt, const std::set<node>& C){
		double delta = (intWeight + degInt) / (double) (extWeight - degInt + degExt);
		return delta - currentQ;
	};

    /*
     * objective function L
     * @return quality difference for the move of v to C
     */
    auto deltaL = [&](node v, double degInt, double degExt, std::set<node>& C){
    	C.insert(v);
    	double numerator = 2.0 * (intWeight + degInt) * boundary(C).size();
    	double denominator = C.size() * (extWeight - degInt + degExt);
    	C.erase(v);
        return (numerator / denominator) - currentQ;
    };

    std::function<double(node v, double degInt, double degExt, std::set<node>& C)> deltaQ;
    // select quality objective
    if (objective == "M") {
        deltaQ = deltaM;
    } else if (objective == "L") {
        deltaQ = deltaL;
    } else {
        throw std::runtime_error("unknown objective function");
    }

    // insert seed
    community.insert(s);

    // for M, quality of {s} is 0.0

	double dQMax;
	node vMax;
	do {
        // get values for current community
        assert(std::make_pair(intWeight, extWeight) == intExtWeight(community));
        // scan shell for node with maximum quality improvement
		dQMax = 0.0; 	// maximum quality improvement
		vMax = none;
//		for (node v : shell(community)) {
		for (const auto& vs : currentShell) {
            // get values for current node
			assert(intExtDeg(vs.first, community) == std::make_pair(vs.second.degInt, vs.second.degExt));

			double dQ = deltaQ(vs.first, vs.second.degInt, vs.second.degExt, community);
			TRACE("dQ: ", dQ);
			if (dQ >= dQMax) {
				vMax = vs.first;
				dQMax = dQ;
			}
		}
		TRACE("vMax: ", vMax);
		TRACE("dQMax: ", dQMax);
		if (vMax != none) {
			community.insert(vMax); 	// add best node to community

			currentShell.erase(vMax);	// remove best node from shell

			G.forNeighborsOf(vMax, [&](node, node v, edgeweight ew) { // insert external neighbors of vMax into shell
				if (!in(community, v)) {
					auto it = currentShell.find(v);
					if (it == currentShell.end()) {
						currentShell.insert(std::make_pair(v, node_property_t {.degInt = ew, .degExt = G.weightedDegree(v) - ew}));
					} else {
						it->second.degInt += ew;
						it->second.degExt -= ew;
					}

					extWeight += ew;

					assert(intExtDeg(v, community) == std::make_pair(currentShell[v].degInt, currentShell[v].degExt));
				} else {
					intWeight += ew;
					extWeight -= ew;
				}
			});
            currentQ += dQMax;     // update current community quality
			TRACE("community: ", community);
		}
	} while (vMax != none);

	return community;
}

} /* namespace NetworKit */
<commit_msg>scd: Speed up GCE computation a tiny bit<commit_after>/* GCE.cpp
 *
 * Created on: 06.05.2013
 * Author: cls
 */

#include "GCE.h"
#include <unordered_map>

namespace NetworKit {

GCE::GCE(const Graph& G, std::string objective) : SelectiveCommunityDetector(G), objective(objective) {
	if (G.numberOfSelfLoops() > 0) {
		throw std::runtime_error("Graphs with self-loops are not supported in GCE");
	}
}

std::map<node, std::set<node> >  GCE::run(std::set<unsigned int>& seeds) {
    std::map<node, std::set<node> > result;
    for (auto seed : seeds) {
        result[seed] = expandSeed(seed);
    }
    return result;
}

template <bool objectiveIsM>
std::set<node> expandseed_internal(const Graph&G, node s) {
    /**
    * Check if set contains node.
    */
	auto in = [](const std::set<node>& A, node x) {
		return (A.find(x) != A.end());
	};

	std::set<node> community;

	// values per community
	double intWeight = 0;
    double extWeight = 0;

	struct node_property_t {
		double degInt;
		double degExt;
	};

	std::unordered_map<node, node_property_t> currentShell;

	G.forNeighborsOf(s, [&](node, node u, edgeweight ew) {
		currentShell.insert(std::make_pair(u, node_property_t {.degInt =  ew, .degExt = G.weightedDegree(u) - ew}));
		extWeight += ew;
	});

    double currentQ = 0.0; // current community quality

    auto boundary = [&](const std::set<node>& C) {
		std::set<node> sh;
		for (const auto &s : currentShell) {
			G.forNeighborsOf(s.first, [&](node u){
				if (!in(C, u)) {
					sh.insert(s.first);
				}
			});
		}
		return sh;
	};

#ifndef NDEBUG
	/**
	 * internal and external weighted degree of a node with respect to the community
	 */
	auto intExtDeg = [&](node v, const std::set<node>& C) {
		double degInt = 0;
		double degExt = 0;
		G.forNeighborsOf(v, [&](node, node u, edgeweight ew) {
			if (in(C, u)) {
				degInt += ew;
			} else {
				degExt += ew;
			}
		});
		return std::make_pair(degInt, degExt);
	};

    auto intExtWeight = [&](const std::set<node>& community) {
        double internal = 0;
        double external = 0;
        for (node u : community) {
            G.forEdgesOf(u, [&](node, node v, edgeweight ew) {
                if (in(community, v)) {
                    internal += ew;
                } else {
                    external += ew;
                }
            });
        }
        internal = internal / 2;    // internal edges were counted twice
        return std::make_pair(internal, external);
    };
#endif

    /*
     * objective function M
     * @return quality difference for the move of v to C
     */
	auto deltaM = [&](node, double degInt, double degExt, const std::set<node>& C){
		double delta = (intWeight + degInt) / (double) (extWeight - degInt + degExt);
		return delta - currentQ;
	};

    /*
     * objective function L
     * @return quality difference for the move of v to C
     */
    auto deltaL = [&](node v, double degInt, double degExt, std::set<node>& C){
    	C.insert(v);
    	double numerator = 2.0 * (intWeight + degInt) * boundary(C).size();
    	double denominator = C.size() * (extWeight - degInt + degExt);
    	C.erase(v);
        return (numerator / denominator) - currentQ;
    };

    // select quality objective
    auto deltaQ = [&](node v, double degInt, double degExt, std::set<node>& C) -> double {
	if (objectiveIsM) {
	    return deltaM(v, degInt, degExt, C);
	} else {
	    return deltaL(v, degInt, degExt, C);
	}
    };

    // insert seed
    community.insert(s);

    // for M, quality of {s} is 0.0

	double dQMax;
	node vMax;
	do {
        // get values for current community
        assert(std::make_pair(intWeight, extWeight) == intExtWeight(community));
        // scan shell for node with maximum quality improvement
		dQMax = 0.0; 	// maximum quality improvement
		vMax = none;
//		for (node v : shell(community)) {
		for (const auto& vs : currentShell) {
            // get values for current node
			assert(intExtDeg(vs.first, community) == std::make_pair(vs.second.degInt, vs.second.degExt));

			double dQ = deltaQ(vs.first, vs.second.degInt, vs.second.degExt, community);
			TRACE("dQ: ", dQ);
			if (dQ >= dQMax) {
				vMax = vs.first;
				dQMax = dQ;
			}
		}
		TRACE("vMax: ", vMax);
		TRACE("dQMax: ", dQMax);
		if (vMax != none) {
			community.insert(vMax); 	// add best node to community

			currentShell.erase(vMax);	// remove best node from shell

			G.forNeighborsOf(vMax, [&](node, node v, edgeweight ew) { // insert external neighbors of vMax into shell
				if (!in(community, v)) {
					auto it = currentShell.find(v);
					if (it == currentShell.end()) {
						currentShell.insert(std::make_pair(v, node_property_t {.degInt = ew, .degExt = G.weightedDegree(v) - ew}));
					} else {
						it->second.degInt += ew;
						it->second.degExt -= ew;
					}

					extWeight += ew;

					assert(intExtDeg(v, community) == std::make_pair(currentShell[v].degInt, currentShell[v].degExt));
				} else {
					intWeight += ew;
					extWeight -= ew;
				}
			});
            currentQ += dQMax;     // update current community quality
			TRACE("community: ", community);
		}
	} while (vMax != none);

	return community;
}

std::set<node> GCE::expandSeed(node s) {
    if (objective == "M") {
        return expandseed_internal<true>(G, s);
    } else if (objective == "L") {
        return expandseed_internal<false>(G, s);
    } else {
        throw std::runtime_error("unknown objective function");
    }
};

} /* namespace NetworKit */
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Highlight.cpp
 *  @brief  EC_Highlight enables visual highlighting effect for of scene entity.
 *  @note   The entity must have EC_Mesh component available to be useful
 */

#include "DebugOperatorNew.h"
#include "EC_Highlight.h"

#include "Framework.h"
#include "AssetAPI.h"
#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "OgreMaterialAsset.h"
#include "EC_Placeable.h"
#include "EC_Mesh.h"
#include "LoggingFunctions.h"
#include "AssetAPI.h"

#include <QTimer>

#include <OgreMaterial.h>
#include <OgreTechnique.h>
#include <OgrePass.h>

#include "MemoryLeakCheck.h"

EC_Highlight::EC_Highlight(SceneManager* scene) :
    IComponent(scene),
    visible(this, "Is visible", false),
    solidColor(this, "Solid color", Color(0.3f, 0.5f, 0.1f, 0.5f)),
    outlineColor(this, "Outline color", Color(1.0f, 1.0f, 1.0f, 0.5f)),
    reapplyPending_(false),
    inApply_(false)
{
    connect(this, SIGNAL(ParentEntitySet()), SLOT(UpdateSignals()));
    connect(this, SIGNAL(AttributeChanged(IAttribute*, AttributeChange::Type)), SLOT(OnAttributeUpdated(IAttribute*)));
}

EC_Highlight::~EC_Highlight()
{
    Hide();
}

void  EC_Highlight::Show()
{
    if (mesh_.expired())
        return;

    inApply_ = true;

    // Remove old materials first if they exist
    Hide();

    EC_Mesh* mesh = mesh_.lock().get();
    AssetAPI* assetAPI = framework_->Asset();
    entity_id_t entityID = GetParentEntity()->GetId();

    // Clone all valid material assets that we can find from the mesh
    /// \todo Currently will clone the same material several times if used on several submeshes
    /// \todo What if the material is yet pending, or is not an asset (LitTextured)
    AssetReferenceList materialList = mesh->meshMaterial.Get();
    for(int i = 0; i < materialList.Size(); ++i)
    {
        if (!materialList[i].ref.isEmpty())
        {
            QString assetFullName = assetAPI->ResolveAssetRef("", materialList[i].ref);
            AssetPtr asset = assetAPI->GetAsset(assetFullName);
            if ((asset) && (asset->IsLoaded()) && (dynamic_cast<OgreMaterialAsset*>(asset.get())))
            {
                /// \todo The material emits an error print when cloning, due to attempting to resolve already sanitated assetrefs
                AssetPtr clone = asset->Clone("EC_Highlight_" + QString::number(entityID) + "_" + QString::number(i) + ".material");
                if (clone)
                {
                    OgreMaterialAsset* matAsset = dynamic_cast<OgreMaterialAsset*>(clone.get());
                    CreateHighlightToOgreMaterial(matAsset);
                    mesh->SetMaterial(i, clone->Name());
                    materials_.push_back(clone);
                }
            }
        }
    }

    inApply_ = false;
}

void EC_Highlight::Hide()
{
    if (!mesh_.expired())
    {
        // Restore mesh component's original materials to hide highlight effect
        EC_Mesh* mesh = mesh_.lock().get();
        mesh->ApplyMaterial();
    }

    // Destroy all the highlight materials
    AssetAPI* assetAPI = framework_->Asset();
    for (unsigned i = 0; i < materials_.size(); ++i)
        assetAPI->ForgetAsset(materials_[i], false);
    materials_.clear();
}

bool EC_Highlight::IsVisible() const
{
    return materials_.size() > 0;
}

void EC_Highlight::UpdateSignals()
{
    Entity* parent = GetParentEntity();
    if (parent)
    {
        // Connect to ComponentAdded/Removed signals of the parent entity, so we can check when the mesh component gets added or removed
        connect(parent, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), SLOT(AcquireMesh()));
        connect(parent, SIGNAL(ComponentRemoved(IComponent*, AttributeChange::Type)), SLOT(OnComponentRemoved(IComponent*, AttributeChange::Type)));
        // Also try to acquire the mesh component immediately
        AcquireMesh();
    }
}

void EC_Highlight::OnComponentRemoved(IComponent* component, AttributeChange::Type change)
{
    if (component == mesh_.lock().get())
    {
        Hide();
        mesh_.reset();
    }
}

void EC_Highlight::AcquireMesh()
{
    // Return if already acquired
    if (!mesh_.expired())
        return;

    mesh_ = GetParentEntity()->GetComponent<EC_Mesh>();

    EC_Mesh* mesh = mesh_.lock().get();
    if (mesh)
    {
        // Connect to mesh & material change signals so we can reapply the highlight
        connect(mesh, SIGNAL(MeshChanged()), this, SLOT(TriggerReapply()), Qt::UniqueConnection);
        connect(mesh, SIGNAL(MaterialChanged(uint, const QString &)), this, SLOT(TriggerReapply()), Qt::UniqueConnection);

        // Also show right now if highlight active
        if (visible.Get())
            Show();
    }
}

void EC_Highlight::OnAttributeUpdated(IAttribute *attribute)
{
    if (attribute == &visible)
    {
        if (visible.Get())
            Show();
        else
            Hide();
    }

    if ((attribute == &solidColor) || (attribute == &outlineColor))
        ApplyHighlightColors();
}

void EC_Highlight::TriggerReapply()
{
    // Disregard signal if in the middle of applying highlight
    if (inApply_)
        return;

    // We might get multiple requests to reapply, but actually execute on the next frame, so that we don't do needless recreation of materials
    if ((!reapplyPending_) && (visible.Get()))
    {
        reapplyPending_ = true;
        QTimer::singleShot(0, this, SLOT(ReapplyHighlight()));
    }
}

void EC_Highlight::ReapplyHighlight()
{
    if (visible.Get())
        Show();
    reapplyPending_ = false;
}

void EC_Highlight::CreateHighlightToOgreMaterial(OgreMaterialAsset* mat)
{
    if (!mat)
        return;

    unsigned numTech = mat->GetNumTechniques();
    for (unsigned i = 0; i < numTech; ++i)
    {
        int pass1 = mat->CreatePass(i);
        int pass2 = mat->CreatePass(i);

        // Setting the shaders requires the SolidAmbient.material to exist in the resource groups, so that the shaders exist
        mat->SetLighting(i, pass1, false);
        mat->SetSceneBlend(i, pass1, Ogre::SBT_TRANSPARENT_ALPHA);
        mat->SetDepthWrite(i, pass1, false);
        mat->SetDepthBias(i, pass1, 0.001f);
        mat->SetVertexShader(i, pass1, "SolidAmbientVP");
        mat->SetPixelShader(i, pass1, "SolidAmbientFP");
        mat->SetAmbientColor(i, pass1, solidColor.Get());

        mat->SetLighting(i, pass2, false);
        mat->SetSceneBlend(i, pass2, Ogre::SBT_TRANSPARENT_ALPHA);
        mat->SetDepthWrite(i, pass2, false);
        mat->SetDepthBias(i, pass2, 0.002f);
        mat->SetVertexShader(i, pass2, "SolidAmbientVP");
        mat->SetPixelShader(i, pass2, "SolidAmbientFP");
        mat->SetAmbientColor(i, pass2, outlineColor.Get());
        mat->SetPolygonMode(i, pass2, Ogre::PM_WIREFRAME);
    }
}

void EC_Highlight::ApplyHighlightColors()
{
    for (unsigned i = 0; i < materials_.size(); ++i)
    {
        OgreMaterialAsset* mat = dynamic_cast<OgreMaterialAsset*>(materials_[i].get());
        unsigned numTech = mat->GetNumTechniques();
        for (unsigned i = 0; i < numTech; ++i)
        {
            unsigned numPasses = mat->GetNumPasses(i);
            // Modify the diffuse color of the last 2 passes
            // (this should be a highlight material that we added the 2 passes to)
            if (numPasses >= 2)
            {
                mat->SetAmbientColor(i, numPasses - 2, solidColor.Get());
                mat->SetAmbientColor(i, numPasses - 1, outlineColor.Get());
            }
        }
    }
}
<commit_msg>Use a lot higher depth bias in EC_Highlight to avoid z fighting issues.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Highlight.cpp
 *  @brief  EC_Highlight enables visual highlighting effect for of scene entity.
 *  @note   The entity must have EC_Mesh component available to be useful
 */

#include "DebugOperatorNew.h"
#include "EC_Highlight.h"

#include "Framework.h"
#include "AssetAPI.h"
#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
#include "OgreMaterialUtils.h"
#include "OgreMaterialAsset.h"
#include "EC_Placeable.h"
#include "EC_Mesh.h"
#include "LoggingFunctions.h"
#include "AssetAPI.h"

#include <QTimer>

#include <OgreMaterial.h>
#include <OgreTechnique.h>
#include <OgrePass.h>

#include "MemoryLeakCheck.h"

EC_Highlight::EC_Highlight(SceneManager* scene) :
    IComponent(scene),
    visible(this, "Is visible", false),
    solidColor(this, "Solid color", Color(0.3f, 0.5f, 0.1f, 0.5f)),
    outlineColor(this, "Outline color", Color(1.0f, 1.0f, 1.0f, 0.5f)),
    reapplyPending_(false),
    inApply_(false)
{
    connect(this, SIGNAL(ParentEntitySet()), SLOT(UpdateSignals()));
    connect(this, SIGNAL(AttributeChanged(IAttribute*, AttributeChange::Type)), SLOT(OnAttributeUpdated(IAttribute*)));
}

EC_Highlight::~EC_Highlight()
{
    Hide();
}

void  EC_Highlight::Show()
{
    if (mesh_.expired())
        return;

    inApply_ = true;

    // Remove old materials first if they exist
    Hide();

    EC_Mesh* mesh = mesh_.lock().get();
    AssetAPI* assetAPI = framework_->Asset();
    entity_id_t entityID = GetParentEntity()->GetId();

    // Clone all valid material assets that we can find from the mesh
    /// \todo Currently will clone the same material several times if used on several submeshes
    /// \todo What if the material is yet pending, or is not an asset (LitTextured)
    AssetReferenceList materialList = mesh->meshMaterial.Get();
    for(int i = 0; i < materialList.Size(); ++i)
    {
        if (!materialList[i].ref.isEmpty())
        {
            QString assetFullName = assetAPI->ResolveAssetRef("", materialList[i].ref);
            AssetPtr asset = assetAPI->GetAsset(assetFullName);
            if ((asset) && (asset->IsLoaded()) && (dynamic_cast<OgreMaterialAsset*>(asset.get())))
            {
                /// \todo The material emits an error print when cloning, due to attempting to resolve already sanitated assetrefs
                AssetPtr clone = asset->Clone("EC_Highlight_" + QString::number(entityID) + "_" + QString::number(i) + ".material");
                if (clone)
                {
                    OgreMaterialAsset* matAsset = dynamic_cast<OgreMaterialAsset*>(clone.get());
                    CreateHighlightToOgreMaterial(matAsset);
                    mesh->SetMaterial(i, clone->Name());
                    materials_.push_back(clone);
                }
            }
        }
    }

    inApply_ = false;
}

void EC_Highlight::Hide()
{
    if (!mesh_.expired())
    {
        // Restore mesh component's original materials to hide highlight effect
        EC_Mesh* mesh = mesh_.lock().get();
        mesh->ApplyMaterial();
    }

    // Destroy all the highlight materials
    AssetAPI* assetAPI = framework_->Asset();
    for (unsigned i = 0; i < materials_.size(); ++i)
        assetAPI->ForgetAsset(materials_[i], false);
    materials_.clear();
}

bool EC_Highlight::IsVisible() const
{
    return materials_.size() > 0;
}

void EC_Highlight::UpdateSignals()
{
    Entity* parent = GetParentEntity();
    if (parent)
    {
        // Connect to ComponentAdded/Removed signals of the parent entity, so we can check when the mesh component gets added or removed
        connect(parent, SIGNAL(ComponentAdded(IComponent*, AttributeChange::Type)), SLOT(AcquireMesh()));
        connect(parent, SIGNAL(ComponentRemoved(IComponent*, AttributeChange::Type)), SLOT(OnComponentRemoved(IComponent*, AttributeChange::Type)));
        // Also try to acquire the mesh component immediately
        AcquireMesh();
    }
}

void EC_Highlight::OnComponentRemoved(IComponent* component, AttributeChange::Type change)
{
    if (component == mesh_.lock().get())
    {
        Hide();
        mesh_.reset();
    }
}

void EC_Highlight::AcquireMesh()
{
    // Return if already acquired
    if (!mesh_.expired())
        return;

    mesh_ = GetParentEntity()->GetComponent<EC_Mesh>();

    EC_Mesh* mesh = mesh_.lock().get();
    if (mesh)
    {
        // Connect to mesh & material change signals so we can reapply the highlight
        connect(mesh, SIGNAL(MeshChanged()), this, SLOT(TriggerReapply()), Qt::UniqueConnection);
        connect(mesh, SIGNAL(MaterialChanged(uint, const QString &)), this, SLOT(TriggerReapply()), Qt::UniqueConnection);

        // Also show right now if highlight active
        if (visible.Get())
            Show();
    }
}

void EC_Highlight::OnAttributeUpdated(IAttribute *attribute)
{
    if (attribute == &visible)
    {
        if (visible.Get())
            Show();
        else
            Hide();
    }

    if ((attribute == &solidColor) || (attribute == &outlineColor))
        ApplyHighlightColors();
}

void EC_Highlight::TriggerReapply()
{
    // Disregard signal if in the middle of applying highlight
    if (inApply_)
        return;

    // We might get multiple requests to reapply, but actually execute on the next frame, so that we don't do needless recreation of materials
    if ((!reapplyPending_) && (visible.Get()))
    {
        reapplyPending_ = true;
        QTimer::singleShot(0, this, SLOT(ReapplyHighlight()));
    }
}

void EC_Highlight::ReapplyHighlight()
{
    if (visible.Get())
        Show();
    reapplyPending_ = false;
}

void EC_Highlight::CreateHighlightToOgreMaterial(OgreMaterialAsset* mat)
{
    if (!mat)
        return;

    unsigned numTech = mat->GetNumTechniques();
    for (unsigned i = 0; i < numTech; ++i)
    {
        int pass1 = mat->CreatePass(i);
        int pass2 = mat->CreatePass(i);

        // Setting the shaders requires the SolidAmbient.material to exist in the resource groups, so that the shaders exist
        mat->SetLighting(i, pass1, false);
        mat->SetSceneBlend(i, pass1, Ogre::SBT_TRANSPARENT_ALPHA);
        mat->SetDepthWrite(i, pass1, false);
        mat->SetDepthBias(i, pass1, 1.f);
        mat->SetVertexShader(i, pass1, "SolidAmbientVP");
        mat->SetPixelShader(i, pass1, "SolidAmbientFP");
        mat->SetAmbientColor(i, pass1, solidColor.Get());

        mat->SetLighting(i, pass2, false);
        mat->SetSceneBlend(i, pass2, Ogre::SBT_TRANSPARENT_ALPHA);
        mat->SetDepthWrite(i, pass2, false);
        mat->SetDepthBias(i, pass2, 2.f);
        mat->SetVertexShader(i, pass2, "SolidAmbientVP");
        mat->SetPixelShader(i, pass2, "SolidAmbientFP");
        mat->SetAmbientColor(i, pass2, outlineColor.Get());
        mat->SetPolygonMode(i, pass2, Ogre::PM_WIREFRAME);
    }
}

void EC_Highlight::ApplyHighlightColors()
{
    for (unsigned i = 0; i < materials_.size(); ++i)
    {
        OgreMaterialAsset* mat = dynamic_cast<OgreMaterialAsset*>(materials_[i].get());
        unsigned numTech = mat->GetNumTechniques();
        for (unsigned i = 0; i < numTech; ++i)
        {
            unsigned numPasses = mat->GetNumPasses(i);
            // Modify the diffuse color of the last 2 passes
            // (this should be a highlight material that we added the 2 passes to)
            if (numPasses >= 2)
            {
                mat->SetAmbientColor(i, numPasses - 2, solidColor.Get());
                mat->SetAmbientColor(i, numPasses - 1, outlineColor.Get());
            }
        }
    }
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program or 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "razormodman.h"
#include <razorqt/razorsettings.h>
#include <qtxdg/xdgautostart.h>

#include <QtDebug>
#include <QDBusInterface>
#include <QCoreApplication>
#include <QMessageBox>
#include "wmselectdialog.h"
#include <razorqt/xfitman.h>

#define MAX_CRASHES_PER_APP 5

/**
 * @brief the constructor, needs a valid modules.conf
 */
RazorModuleManager::RazorModuleManager(const QString & config, const QString & windowManager, QObject* parent)
    : QObject(parent),
    mConfig(config)
{
    m_power = new QDBusInterface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer",
                               "org.freedesktop.Hal.Device.SystemPowerManagement",
                               QDBusConnection::systemBus());

    qDebug() << __FILE__ << ":" << __LINE__ << "Session" << config << "about to launch (deafult 'session')";
    if (mConfig.isEmpty())
        mConfig = "session";

    RazorSettings s(mConfig);

    // first - set some user defined environment variables (like TERM...)
    s.beginGroup("environment");
    QByteArray envVal;
    foreach (QString i, s.childKeys())
    {
        envVal = s.value(i).toByteArray();
        razor_setenv(i.toUtf8().constData(), envVal);
    }
    s.endGroup();

    // then rest of the config:

    // window manager
    // If the WM is active do not run WM.
    if (!xfitMan().isWindowManagerActive())
    {
        QString wm;
        if (windowManager.isNull())
        {
            wm = s.value("windowmanager").toString();
            if (wm.isEmpty())
            {
                wm = showWmSelectDialog();
                s.setValue("windowmanager", wm);
                s.sync();
            }
            //qDebug() << "Using window manager from config file" << wm;
        }
        else
        {
            wm = windowManager;
            //qDebug() << "Using window manager specified with command line" << windowManager;
        }

        QProcess * wmProcess = new QProcess(this);
        wmProcess->start(wm);
        connect(wmProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
                this, SLOT(logout()));
    }
    // window manager

    // modules
    s.beginGroup("modules");
    foreach(QString i, s.childKeys())
    {
        bool start = s.value(i, true).toBool();
        if (!start)
            continue;

        QProcess* tmp = new QProcess(this);
        tmp->start(i);
        // we have to ensure modules start before we'll process
        // autostart (some apps may require tray for example)
        tmp->waitForStarted();

        procMap[i] = tmp;

        connect(tmp, SIGNAL(finished(int, QProcess::ExitStatus)),
                this, SLOT(restartModules(int, QProcess::ExitStatus)));
    }
    s.endGroup();

    // HACK: ensure all is prepared and running for 3rd party apps.
    //       There is always some chance to start an app when eg. panel won't be ready yet.
    //       I faced this issue with qsynergy (petr).
    sleep(2); // a guess-what constant...

    // XDG autostart
    foreach (XdgDesktopFile f, XdgAutoStart::desktopFileList())
    {
        f.startDetached();
    }

    m_crashTimer.setInterval(60000);
    connect(&m_crashTimer, SIGNAL(timeout()), this, SLOT(resetCrashReport()));
}

void RazorModuleManager::restartModules(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "void RazorModuleManager::restartModules() called and it's wrong. Something is failing" << sender();
    QProcess * proc = qobject_cast<QProcess*>(sender());
    Q_ASSERT(proc);
    QString procName;

    ModulesMapIterator i(procMap);
    while (i.hasNext())
    {
        i.next();
        if (i.value() == proc)
        {
            procName = i.key();
            break;
        }
    }

    switch (exitStatus)
    {
        case QProcess::NormalExit:
            qDebug() << "Process" << procName << "(" << proc << ") exited correctly.";
            break;
        case QProcess::CrashExit:
        {
            qDebug() << "Process" << procName << "(" << proc << ") has to be restarted";
            if (!m_crashReport.contains(procName))
                m_crashReport[procName] = 0;
            int stat = m_crashReport[procName]++;
            if (stat >= MAX_CRASHES_PER_APP)
            {
                procMap.take(procName)->deleteLater();
                QMessageBox::warning(0, tr("Razor Session Crash Report"),
                                    tr("Application '%1' crashed too many times. Its autorestart has been disabled for current session.").arg(procName));
            }
            else
            {
                proc->start(procName);
            }
            break;
        }
    }

}

RazorModuleManager::~RazorModuleManager()
{
    delete m_power;
}

/**
* @brief this logs us out by terminating our session
**/
void RazorModuleManager::logout()
{
    // modules
    ModulesMapIterator i(procMap);
    while (i.hasNext())
    {
        i.next();
        qDebug() << "Module logout" << i.key();
        QProcess * p = i.value();
        p->blockSignals(true);
        p->terminate();
        if (!p->waitForFinished())
            qDebug() << "Module" << p << "rejected to close correctly. Kill it down.";
    }
    QCoreApplication::exit(0);
}

QString RazorModuleManager::showWmSelectDialog()
{
    WmSelectDialog dlg;
    dlg.exec();
    return dlg.windowManager();
}

void RazorModuleManager::resetCrashReport()
{
    m_crashReport.clear();
}

void razor_setenv(const char *env, const QByteArray &value)
{
    qDebug() << "Environment variable" << env << "=" << value;
    qputenv(env, value);
}

void razor_setenv_prepend(const char *env, const QByteArray &value, const QByteArray &separator)
{
    QByteArray orig(qgetenv(env));
    orig = orig.prepend(separator);
    orig = orig.prepend(value);
    qDebug() << "Setting special" << env << " variable:" << orig;
    razor_setenv(env, orig);
}

<commit_msg>Razor-session:  Wait until the WM loads<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Razor - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Petr Vanek <petr@scribus.info>
 *
 * This program or 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "razormodman.h"
#include <razorqt/razorsettings.h>
#include <qtxdg/xdgautostart.h>

#include <QtDebug>
#include <QDBusInterface>
#include <QCoreApplication>
#include <QMessageBox>
#include "wmselectdialog.h"
#include <razorqt/xfitman.h>

#define MAX_CRASHES_PER_APP 5

/**
 * @brief the constructor, needs a valid modules.conf
 */
RazorModuleManager::RazorModuleManager(const QString & config, const QString & windowManager, QObject* parent)
    : QObject(parent),
    mConfig(config)
{
    m_power = new QDBusInterface("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer",
                               "org.freedesktop.Hal.Device.SystemPowerManagement",
                               QDBusConnection::systemBus());

    qDebug() << __FILE__ << ":" << __LINE__ << "Session" << config << "about to launch (deafult 'session')";
    if (mConfig.isEmpty())
        mConfig = "session";

    RazorSettings s(mConfig);

    // first - set some user defined environment variables (like TERM...)
    s.beginGroup("environment");
    QByteArray envVal;
    foreach (QString i, s.childKeys())
    {
        envVal = s.value(i).toByteArray();
        razor_setenv(i.toUtf8().constData(), envVal);
    }
    s.endGroup();

    // then rest of the config:

    // window manager
    // If the WM is active do not run WM.
    if (!xfitMan().isWindowManagerActive())
    {
        QString wm;
        if (windowManager.isNull())
        {
            wm = s.value("windowmanager").toString();
            if (wm.isEmpty())
            {
                wm = showWmSelectDialog();
                s.setValue("windowmanager", wm);
                s.sync();
            }
            //qDebug() << "Using window manager from config file" << wm;
        }
        else
        {
            wm = windowManager;
            //qDebug() << "Using window manager specified with command line" << windowManager;
        }

        QProcess * wmProcess = new QProcess(this);
        wmProcess->start(wm);
        connect(wmProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
                this, SLOT(logout()));
    }

    // Wait until the WM loads
    int waitCnt = 300;
    while (!xfitMan().isWindowManagerActive() && waitCnt)
    {
        qDebug() << "******************** Wait until the WM loads" << waitCnt;
        waitCnt--;
        usleep(100000);
    }

    // window manager

    // modules
    s.beginGroup("modules");
    foreach(QString i, s.childKeys())
    {
        bool start = s.value(i, true).toBool();
        if (!start)
            continue;

        QProcess* tmp = new QProcess(this);
        tmp->start(i);
        // we have to ensure modules start before we'll process
        // autostart (some apps may require tray for example)
        tmp->waitForStarted();

        procMap[i] = tmp;

        connect(tmp, SIGNAL(finished(int, QProcess::ExitStatus)),
                this, SLOT(restartModules(int, QProcess::ExitStatus)));
    }
    s.endGroup();

    // HACK: ensure all is prepared and running for 3rd party apps.
    //       There is always some chance to start an app when eg. panel won't be ready yet.
    //       I faced this issue with qsynergy (petr).
    sleep(2); // a guess-what constant...

    // XDG autostart
    foreach (XdgDesktopFile f, XdgAutoStart::desktopFileList())
    {
        f.startDetached();
    }

    m_crashTimer.setInterval(60000);
    connect(&m_crashTimer, SIGNAL(timeout()), this, SLOT(resetCrashReport()));
}

void RazorModuleManager::restartModules(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "void RazorModuleManager::restartModules() called and it's wrong. Something is failing" << sender();
    QProcess * proc = qobject_cast<QProcess*>(sender());
    Q_ASSERT(proc);
    QString procName;

    ModulesMapIterator i(procMap);
    while (i.hasNext())
    {
        i.next();
        if (i.value() == proc)
        {
            procName = i.key();
            break;
        }
    }

    switch (exitStatus)
    {
        case QProcess::NormalExit:
            qDebug() << "Process" << procName << "(" << proc << ") exited correctly.";
            break;
        case QProcess::CrashExit:
        {
            qDebug() << "Process" << procName << "(" << proc << ") has to be restarted";
            if (!m_crashReport.contains(procName))
                m_crashReport[procName] = 0;
            int stat = m_crashReport[procName]++;
            if (stat >= MAX_CRASHES_PER_APP)
            {
                procMap.take(procName)->deleteLater();
                QMessageBox::warning(0, tr("Razor Session Crash Report"),
                                    tr("Application '%1' crashed too many times. Its autorestart has been disabled for current session.").arg(procName));
            }
            else
            {
                proc->start(procName);
            }
            break;
        }
    }

}

RazorModuleManager::~RazorModuleManager()
{
    delete m_power;
}

/**
* @brief this logs us out by terminating our session
**/
void RazorModuleManager::logout()
{
    // modules
    ModulesMapIterator i(procMap);
    while (i.hasNext())
    {
        i.next();
        qDebug() << "Module logout" << i.key();
        QProcess * p = i.value();
        p->blockSignals(true);
        p->terminate();
        if (!p->waitForFinished())
            qDebug() << "Module" << p << "rejected to close correctly. Kill it down.";
    }
    QCoreApplication::exit(0);
}

QString RazorModuleManager::showWmSelectDialog()
{
    WmSelectDialog dlg;
    dlg.exec();
    return dlg.windowManager();
}

void RazorModuleManager::resetCrashReport()
{
    m_crashReport.clear();
}

void razor_setenv(const char *env, const QByteArray &value)
{
    qDebug() << "Environment variable" << env << "=" << value;
    qputenv(env, value);
}

void razor_setenv_prepend(const char *env, const QByteArray &value, const QByteArray &separator)
{
    QByteArray orig(qgetenv(env));
    orig = orig.prepend(separator);
    orig = orig.prepend(value);
    qDebug() << "Setting special" << env << " variable:" << orig;
    razor_setenv(env, orig);
}

<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

namespace chromeos {

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton

// static
const int PowerMenuButton::kNumPowerImages = 12;

PowerMenuButton::PowerMenuButton()
    : StatusAreaButton(this),
      battery_is_present_(false),
      line_power_on_(false),
      battery_fully_charged_(false),
      battery_percentage_(0.0),
      icon_id_(-1),
      ALLOW_THIS_IN_INITIALIZER_LIST(power_menu_(this)) {
  UpdateIconAndLabelInfo();
  CrosLibrary::Get()->GetPowerLibrary()->AddObserver(this);
}

PowerMenuButton::~PowerMenuButton() {
  CrosLibrary::Get()->GetPowerLibrary()->RemoveObserver(this);
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, menus::MenuModel implementation:

int PowerMenuButton::GetItemCount() const {
  return 2;
}

menus::MenuModel::ItemType PowerMenuButton::GetTypeAt(int index) const {
  return menus::MenuModel::TYPE_COMMAND;
}

string16 PowerMenuButton::GetLabelAt(int index) const {
  // The first item shows the percentage of battery left.
  if (index == 0) {
    return l10n_util::GetStringFUTF16(IDS_STATUSBAR_BATTERY_PERCENTAGE,
        base::IntToString16(static_cast<int>(battery_percentage_)));
  }

  if (index == 1) {
    // The second item shows the battery is charged if it is.
    if (battery_fully_charged_)
      return l10n_util::GetStringUTF16(IDS_STATUSBAR_BATTERY_IS_CHARGED);

    // If battery is in an intermediate charge state, we show how much time left.
    base::TimeDelta time = line_power_on_ ? battery_time_to_full_ :
        battery_time_to_empty_;
    if (time.InSeconds() == 0) {
      // If time is 0, then that means we are still calculating how much time.
      // Depending if line power is on, we either show a message saying that we
      // are calculating time until full or calculating remaining time.
      int msg = line_power_on_ ?
          IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_FULL :
          IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_EMPTY;
      return l10n_util::GetStringUTF16(msg);
    } else {
      // Depending if line power is on, we either show a message saying XX:YY
      // until full or XX:YY remaining where XX is number of hours and YY is
      // number of minutes.
      int msg = line_power_on_ ? IDS_STATUSBAR_BATTERY_TIME_UNTIL_FULL :
          IDS_STATUSBAR_BATTERY_TIME_UNTIL_EMPTY;
      int hour = time.InHours();
      int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
      string16 hour_str = base::IntToString16(hour);
      string16 min_str = base::IntToString16(min);
      // Append a "0" before the minute if it's only a single digit.
      if (min < 10)
        min_str = ASCIIToUTF16("0") + min_str;
      return l10n_util::GetStringFUTF16(msg, hour_str, min_str);
    }
  }

  return string16();
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, views::ViewMenuDelegate implementation:

void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
  power_menu_.Rebuild();
  power_menu_.UpdateStates();
  power_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, PowerLibrary::Observer implementation:

void PowerMenuButton::PowerChanged(PowerLibrary* obj) {
  UpdateIconAndLabelInfo();
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, StatusAreaButton implementation:

void PowerMenuButton::DrawPressed(gfx::Canvas* canvas) {
  DrawPowerIcon(canvas, *ResourceBundle::GetSharedInstance().
      GetBitmapNamed(IDR_STATUSBAR_BATTERY_PRESSED));
}

void PowerMenuButton::DrawIcon(gfx::Canvas* canvas) {
  DrawPowerIcon(canvas, icon());
}

void PowerMenuButton::DrawPowerIcon(gfx::Canvas* canvas, SkBitmap icon) {
  // Draw the battery icon 5 pixels down to center it.
  static const int kIconVerticalPadding = 5;
  canvas->DrawBitmapInt(icon, 0, kIconVerticalPadding);
}

void PowerMenuButton::UpdateIconAndLabelInfo() {
  PowerLibrary* cros = CrosLibrary::Get()->GetPowerLibrary();
  if (!cros)
    return;

  bool cros_loaded = CrosLibrary::Get()->EnsureLoaded();
  if (cros_loaded) {
    battery_is_present_ = cros->battery_is_present();
    line_power_on_ = cros->line_power_on();
    battery_fully_charged_ = cros->battery_fully_charged();
    battery_percentage_ = cros->battery_percentage();
    // If fully charged, always show 100% even if internal number is a bit less.
    // Note: we always call cros->battery_percentage() for test predictability.
    if (battery_fully_charged_)
      battery_percentage_ = 100.0;
    battery_time_to_full_ = cros->battery_time_to_full();
    battery_time_to_empty_ = cros->battery_time_to_empty();
  }

  if (!cros_loaded) {
    icon_id_ = IDR_STATUSBAR_BATTERY_UNKNOWN;
  } else if (!battery_is_present_) {
    icon_id_ = IDR_STATUSBAR_BATTERY_MISSING;
  } else if (line_power_on_ && battery_fully_charged_) {
    icon_id_ = IDR_STATUSBAR_BATTERY_CHARGED;
  } else {
    // Get the power image depending on battery percentage. Percentage is
    // from 0 to 100, so we need to convert that to 0 to kNumPowerImages - 1.
    // NOTE: Use an array rather than just calculating a resource number to
    // avoid creating implicit ordering dependencies on the resource values.
    static const int kChargingImages[kNumPowerImages] = {
      IDR_STATUSBAR_BATTERY_CHARGING_1,
      IDR_STATUSBAR_BATTERY_CHARGING_2,
      IDR_STATUSBAR_BATTERY_CHARGING_3,
      IDR_STATUSBAR_BATTERY_CHARGING_4,
      IDR_STATUSBAR_BATTERY_CHARGING_5,
      IDR_STATUSBAR_BATTERY_CHARGING_6,
      IDR_STATUSBAR_BATTERY_CHARGING_7,
      IDR_STATUSBAR_BATTERY_CHARGING_8,
      IDR_STATUSBAR_BATTERY_CHARGING_9,
      IDR_STATUSBAR_BATTERY_CHARGING_10,
      IDR_STATUSBAR_BATTERY_CHARGING_11,
      IDR_STATUSBAR_BATTERY_CHARGING_12,
    };
    static const int kDischargingImages[kNumPowerImages] = {
      IDR_STATUSBAR_BATTERY_DISCHARGING_1,
      IDR_STATUSBAR_BATTERY_DISCHARGING_2,
      IDR_STATUSBAR_BATTERY_DISCHARGING_3,
      IDR_STATUSBAR_BATTERY_DISCHARGING_4,
      IDR_STATUSBAR_BATTERY_DISCHARGING_5,
      IDR_STATUSBAR_BATTERY_DISCHARGING_6,
      IDR_STATUSBAR_BATTERY_DISCHARGING_7,
      IDR_STATUSBAR_BATTERY_DISCHARGING_8,
      IDR_STATUSBAR_BATTERY_DISCHARGING_9,
      IDR_STATUSBAR_BATTERY_DISCHARGING_10,
      IDR_STATUSBAR_BATTERY_DISCHARGING_11,
      IDR_STATUSBAR_BATTERY_DISCHARGING_12,
    };

    int index = static_cast<int>(battery_percentage_ / 100.0 *
                nextafter(static_cast<float>(kNumPowerImages), 0));
    index = std::max(std::min(index, kNumPowerImages - 1), 0);
    icon_id_ = line_power_on_ ?
        kChargingImages[index] : kDischargingImages[index];
  }

  SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id_));
  SetTooltipText(UTF16ToWide(GetLabelAt(0)));
  SchedulePaint();
}

}  // namespace chromeos
<commit_msg>Rebaseline a bunch of tests in repaint since they are correct (except for the grayed-out repainted area we don't support in the image diffs).<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/string_number_conversions.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "gfx/canvas.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

namespace chromeos {

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton

// static
const int PowerMenuButton::kNumPowerImages = 12;

PowerMenuButton::PowerMenuButton()
    : StatusAreaButton(this),
      battery_is_present_(false),
      line_power_on_(false),
      battery_fully_charged_(false),
      battery_percentage_(0.0),
      icon_id_(-1),
      ALLOW_THIS_IN_INITIALIZER_LIST(power_menu_(this)) {
  UpdateIconAndLabelInfo();
  CrosLibrary::Get()->GetPowerLibrary()->AddObserver(this);
}

PowerMenuButton::~PowerMenuButton() {
  CrosLibrary::Get()->GetPowerLibrary()->RemoveObserver(this);
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, menus::MenuModel implementation:

int PowerMenuButton::GetItemCount() const {
  return 2;
}

menus::MenuModel::ItemType PowerMenuButton::GetTypeAt(int index) const {
  return menus::MenuModel::TYPE_COMMAND;
}

string16 PowerMenuButton::GetLabelAt(int index) const {
  // The first item shows the percentage of battery left.
  if (index == 0) {
    return l10n_util::GetStringFUTF16(IDS_STATUSBAR_BATTERY_PERCENTAGE,
        base::IntToString16(static_cast<int>(battery_percentage_)));
  } else if (index == 1) {
    // The second item shows the battery is charged if it is.
    if (battery_fully_charged_)
      return l10n_util::GetStringUTF16(IDS_STATUSBAR_BATTERY_IS_CHARGED);

    // If battery is in an intermediate charge state, show how much time left.
    base::TimeDelta time = line_power_on_ ? battery_time_to_full_ :
        battery_time_to_empty_;
    if (time.InSeconds() == 0) {
      // If time is 0, then that means we are still calculating how much time.
      // Depending if line power is on, we either show a message saying that we
      // are calculating time until full or calculating remaining time.
      int msg = line_power_on_ ?
          IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_FULL :
          IDS_STATUSBAR_BATTERY_CALCULATING_TIME_UNTIL_EMPTY;
      return l10n_util::GetStringUTF16(msg);
    } else {
      // Depending if line power is on, we either show a message saying XX:YY
      // until full or XX:YY remaining where XX is number of hours and YY is
      // number of minutes.
      int msg = line_power_on_ ? IDS_STATUSBAR_BATTERY_TIME_UNTIL_FULL :
          IDS_STATUSBAR_BATTERY_TIME_UNTIL_EMPTY;
      int hour = time.InHours();
      int min = (time - base::TimeDelta::FromHours(hour)).InMinutes();
      string16 hour_str = base::IntToString16(hour);
      string16 min_str = base::IntToString16(min);
      // Append a "0" before the minute if it's only a single digit.
      if (min < 10)
        min_str = ASCIIToUTF16("0") + min_str;
      return l10n_util::GetStringFUTF16(msg, hour_str, min_str);
    }
  } else {
    NOTREACHED();
    return string16();
  }
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, views::ViewMenuDelegate implementation:

void PowerMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
  power_menu_.Rebuild();
  power_menu_.UpdateStates();
  power_menu_.RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, PowerLibrary::Observer implementation:

void PowerMenuButton::PowerChanged(PowerLibrary* obj) {
  UpdateIconAndLabelInfo();
}

////////////////////////////////////////////////////////////////////////////////
// PowerMenuButton, StatusAreaButton implementation:

void PowerMenuButton::DrawPressed(gfx::Canvas* canvas) {
  DrawPowerIcon(canvas, *ResourceBundle::GetSharedInstance().
      GetBitmapNamed(IDR_STATUSBAR_BATTERY_PRESSED));
}

void PowerMenuButton::DrawIcon(gfx::Canvas* canvas) {
  DrawPowerIcon(canvas, icon());
}

void PowerMenuButton::DrawPowerIcon(gfx::Canvas* canvas, SkBitmap icon) {
  // Draw the battery icon 5 pixels down to center it.
  static const int kIconVerticalPadding = 5;
  canvas->DrawBitmapInt(icon, 0, kIconVerticalPadding);
}

void PowerMenuButton::UpdateIconAndLabelInfo() {
  PowerLibrary* cros = CrosLibrary::Get()->GetPowerLibrary();
  if (!cros)
    return;

  bool cros_loaded = CrosLibrary::Get()->EnsureLoaded();
  if (cros_loaded) {
    battery_is_present_ = cros->battery_is_present();
    line_power_on_ = cros->line_power_on();
    battery_fully_charged_ = cros->battery_fully_charged();
    battery_percentage_ = cros->battery_percentage();
    // If fully charged, always show 100% even if internal number is a bit less.
    // Note: we always call cros->battery_percentage() for test predictability.
    if (battery_fully_charged_)
      battery_percentage_ = 100.0;
    battery_time_to_full_ = cros->battery_time_to_full();
    battery_time_to_empty_ = cros->battery_time_to_empty();
  }

  if (!cros_loaded) {
    icon_id_ = IDR_STATUSBAR_BATTERY_UNKNOWN;
  } else if (!battery_is_present_) {
    icon_id_ = IDR_STATUSBAR_BATTERY_MISSING;
  } else if (line_power_on_ && battery_fully_charged_) {
    icon_id_ = IDR_STATUSBAR_BATTERY_CHARGED;
  } else {
    // Get the power image depending on battery percentage. Percentage is
    // from 0 to 100, so we need to convert that to 0 to kNumPowerImages - 1.
    // NOTE: Use an array rather than just calculating a resource number to
    // avoid creating implicit ordering dependencies on the resource values.
    static const int kChargingImages[kNumPowerImages] = {
      IDR_STATUSBAR_BATTERY_CHARGING_1,
      IDR_STATUSBAR_BATTERY_CHARGING_2,
      IDR_STATUSBAR_BATTERY_CHARGING_3,
      IDR_STATUSBAR_BATTERY_CHARGING_4,
      IDR_STATUSBAR_BATTERY_CHARGING_5,
      IDR_STATUSBAR_BATTERY_CHARGING_6,
      IDR_STATUSBAR_BATTERY_CHARGING_7,
      IDR_STATUSBAR_BATTERY_CHARGING_8,
      IDR_STATUSBAR_BATTERY_CHARGING_9,
      IDR_STATUSBAR_BATTERY_CHARGING_10,
      IDR_STATUSBAR_BATTERY_CHARGING_11,
      IDR_STATUSBAR_BATTERY_CHARGING_12,
    };
    static const int kDischargingImages[kNumPowerImages] = {
      IDR_STATUSBAR_BATTERY_DISCHARGING_1,
      IDR_STATUSBAR_BATTERY_DISCHARGING_2,
      IDR_STATUSBAR_BATTERY_DISCHARGING_3,
      IDR_STATUSBAR_BATTERY_DISCHARGING_4,
      IDR_STATUSBAR_BATTERY_DISCHARGING_5,
      IDR_STATUSBAR_BATTERY_DISCHARGING_6,
      IDR_STATUSBAR_BATTERY_DISCHARGING_7,
      IDR_STATUSBAR_BATTERY_DISCHARGING_8,
      IDR_STATUSBAR_BATTERY_DISCHARGING_9,
      IDR_STATUSBAR_BATTERY_DISCHARGING_10,
      IDR_STATUSBAR_BATTERY_DISCHARGING_11,
      IDR_STATUSBAR_BATTERY_DISCHARGING_12,
    };

    int index = static_cast<int>(battery_percentage_ / 100.0 *
                nextafter(static_cast<float>(kNumPowerImages), 0));
    index = std::max(std::min(index, kNumPowerImages - 1), 0);
    icon_id_ = line_power_on_ ?
        kChargingImages[index] : kDischargingImages[index];
  }

  SetIcon(*ResourceBundle::GetSharedInstance().GetBitmapNamed(icon_id_));
  SetTooltipText(UTF16ToWide(GetLabelAt(0)));
  SchedulePaint();
}

}  // namespace chromeos
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/scenario/feature_extractor/feature_extractor.h"

#include <string>

#include "modules/common/adapters/proto/adapter_config.pb.h"
#include "modules/common/math/vec2d.h"
#include "modules/map/hdmap/hdmap_util.h"

using apollo::common::adapter::AdapterConfig;
using apollo::common::math::Vec2d;
using apollo::planning::ADCTrajectory;
using apollo::hdmap::HDMapUtil;
using apollo::hdmap::LaneInfo;
using apollo::hdmap::JunctionInfo;
using JunctionInfoPtr = std::shared_ptr<const JunctionInfo>;
using LaneInfoPtr = std::shared_ptr<const LaneInfo>;

namespace apollo {
namespace prediction {

FeatureExtractor::FeatureExtractor() {
  ego_trajectory_containter_ = dynamic_cast<ADCTrajectoryContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PLANNING_TRAJECTORY));

  pose_container_ = dynamic_cast<PoseContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::LOCALIZATION));
}

FeatureExtractor::~FeatureExtractor() {
}

void FeatureExtractor::ExtractFeatures() {
  SetADCFeature();
  SetLaneFeature();
  SetJunctionFeature();
  // TODO(all) other processes
}

const ScenarioFeature& FeatureExtractor::scenario_feature() const {
  return scenario_feature_;
}

void FeatureExtractor::SetADCFeature() {
  // TODO(all): change this to ego_speed and ego_heading
  scenario_feature_.set_speed(pose_container_->GetSpeed());
  scenario_feature_.set_heading(pose_container_->GetTheta());
  // TODO(all) adc acceleration if needed
}

void FeatureExtractor::SetLaneFeature() {
  LaneInfoPtr curr_lane_info = GetCurrentLane();
  if (curr_lane_info != nullptr) {
    auto position = pose_container_->GetPosition();
    scenario_feature_.set_curr_lane_id(curr_lane_info->id().id());
    double curr_lane_s = 0.0;
    double curr_lane_l = 0.0;
    curr_lane_info->GetProjection(Vec2d{position.x(), position.y()},
                                  &curr_lane_s, &curr_lane_l);
    scenario_feature_.set_curr_lane_s(curr_lane_s);
  }

  // TODO(all) implement neighbor lane features
}

void FeatureExtractor::SetJunctionFeature() {
  JunctionInfoPtr junction = ego_trajectory_containter_->ADCJunction();
  if (junction != nullptr) {
    scenario_feature_.set_junction_id(junction->id().id());
    scenario_feature_.set_dist_to_junction(
        ego_trajectory_containter_->ADCDistanceToJunction());
  }
}

std::shared_ptr<const apollo::hdmap::LaneInfo>
FeatureExtractor::GetCurrentLane() const {
  auto position = pose_container_->GetPosition();
  const ADCTrajectory& adc_trajectory =
      ego_trajectory_containter_->adc_trajectory();
  for (const auto& lane_id : adc_trajectory.lane_id()) {
    LaneInfoPtr lane_info =
        HDMapUtil::BaseMap().GetLaneById(hdmap::MakeMapId(lane_id.id()));
    if (lane_info->IsOnLane(Vec2d{position.x(), position.y()})) {
      return lane_info;
    }
  }
  return nullptr;
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction: refactor set lane feature in scenario<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/scenario/feature_extractor/feature_extractor.h"

#include <string>

#include "modules/common/adapters/proto/adapter_config.pb.h"
#include "modules/common/math/vec2d.h"
#include "modules/map/hdmap/hdmap_util.h"

using apollo::common::adapter::AdapterConfig;
using apollo::common::math::Vec2d;
using apollo::planning::ADCTrajectory;
using apollo::hdmap::HDMapUtil;
using apollo::hdmap::LaneInfo;
using apollo::hdmap::JunctionInfo;
using JunctionInfoPtr = std::shared_ptr<const JunctionInfo>;
using LaneInfoPtr = std::shared_ptr<const LaneInfo>;

namespace apollo {
namespace prediction {

FeatureExtractor::FeatureExtractor() {
  ego_trajectory_containter_ = dynamic_cast<ADCTrajectoryContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PLANNING_TRAJECTORY));

  pose_container_ = dynamic_cast<PoseContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::LOCALIZATION));
}

FeatureExtractor::~FeatureExtractor() {
}

void FeatureExtractor::ExtractFeatures() {
  SetADCFeature();
  SetLaneFeature();
  SetJunctionFeature();
  // TODO(all) other processes
}

const ScenarioFeature& FeatureExtractor::scenario_feature() const {
  return scenario_feature_;
}

void FeatureExtractor::SetADCFeature() {
  // TODO(all): change this to ego_speed and ego_heading
  scenario_feature_.set_speed(pose_container_->GetSpeed());
  scenario_feature_.set_heading(pose_container_->GetTheta());
  // TODO(all) adc acceleration if needed
}

void FeatureExtractor::SetLaneFeature() {
  LaneInfoPtr curr_lane_info = GetCurrentLane();
  if (curr_lane_info == nullptr) {
    AERROR << "ADC is not on any lane.";
    return;
  }
  auto position = pose_container_->GetPosition();
  scenario_feature_.set_curr_lane_id(curr_lane_info->id().id());
  double curr_lane_s = 0.0;
  double curr_lane_l = 0.0;
  curr_lane_info->GetProjection(Vec2d{position.x(), position.y()},
                                &curr_lane_s, &curr_lane_l);
  scenario_feature_.set_curr_lane_s(curr_lane_s);

  // TODO(all) implement neighbor lane features
}

void FeatureExtractor::SetJunctionFeature() {
  JunctionInfoPtr junction = ego_trajectory_containter_->ADCJunction();
  if (junction != nullptr) {
    scenario_feature_.set_junction_id(junction->id().id());
    scenario_feature_.set_dist_to_junction(
        ego_trajectory_containter_->ADCDistanceToJunction());
  }
}

std::shared_ptr<const apollo::hdmap::LaneInfo>
FeatureExtractor::GetCurrentLane() const {
  auto position = pose_container_->GetPosition();
  const ADCTrajectory& adc_trajectory =
      ego_trajectory_containter_->adc_trajectory();
  for (const auto& lane_id : adc_trajectory.lane_id()) {
    LaneInfoPtr lane_info =
        HDMapUtil::BaseMap().GetLaneById(hdmap::MakeMapId(lane_id.id()));
    if (lane_info->IsOnLane(Vec2d{position.x(), position.y()})) {
      return lane_info;
    }
  }
  return nullptr;
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>


<commit_before>/* Copyright (c) 2014 K. Ernest 'iFire' Lee

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */

// Add a class to handle the Solution file locally
// instead of relying on FDesktopPlatformModule.

#include "QtCreatorSourceCodeAccessPrivatePCH.h"
#include "QtCreatorSourceCodeAccessor.h"
#include "DesktopPlatformModule.h"

#define LOCTEXT_NAMESPACE "QtCreatorSourceCodeAccessor"
bool FQtCreatorSourceCodeAccessor::CanAccessSourceCode() const
{
  return FPaths::FileExists(TEXT("/usr/bin/clang"));
}

FName FQtCreatorSourceCodeAccessor::GetFName() const
{
  return FName("QtCreatorSourceCodeAccessor");
}

FText FQtCreatorSourceCodeAccessor::GetNameText() const
{
  return LOCTEXT("QtCreatorDisplayName", "Qt Creator");
}

FText FQtCreatorSourceCodeAccessor::GetDescriptionText() const
{
  return LOCTEXT("QtCreatorDisplayDesc", "Open source code files with Qt Creator");
}

bool FQtCreatorSourceCodeAccessor::OpenSolution()
{
  printf("Yes it got to here.");
  FString FullPath;
  FString SolutionFilenameWithoutExtension = TEXT("UE4");
  FString CodeSolutionFile = SolutionFilenameWithoutExtension + TEXT(".pro");

  if(FDesktopPlatformModule::Get()->GetSolutionPath(FullPath)){
    if ( FPaths::FileExists( FullPath ) )
    {
      FString Editor = FString(TEXT("/usr/bin/qtcreator"));
      FString Args = FString(TEXT("-client "));
      Args.Append(FullPath);
      if(FLinuxPlatformProcess::CreateProc(*Editor,
                                           *Args,
                                           true,
                                           true,
                                           false,
                                           nullptr,
                                           0,
                                           nullptr,
                                           nullptr).IsValid())
        return true;
    }
  }
  return false;
}

bool FQtCreatorSourceCodeAccessor::OpenFileAtLine(const FString& FullPath, int32 LineNumber, int32 ColumnNumber)
{
    FString Editor = FString(TEXT("/usr/bin/qtcreator"));
    FString Args = FString(TEXT("-client "));
    Args.Append(FullPath).Append(TEXT(":")).Append(FString::FromInt(LineNumber));
    if (FLinuxPlatformProcess::CreateProc(*Editor,
                                          *Args,
                                          true,
                                          true,
                                          false,
                                          nullptr,
                                          0,
                                          nullptr,
                                          nullptr).IsValid())
      return true;
  return false;
}

bool FQtCreatorSourceCodeAccessor::OpenSourceFiles(const TArray<FString>& AbsoluteSourcePaths)
{
  for ( const FString& SourcePath : AbsoluteSourcePaths )
  {
    FString Editor = FString(TEXT("/usr/bin/qtcreator"));
    FString Args = FString(TEXT("-client "));
    Args.Append(SourcePath);
    if(!(FLinuxPlatformProcess::CreateProc(*Editor,
                                           *Args,
                                           true,
                                           true,
                                           false,
                                           nullptr,
                                           0,
                                           nullptr,
                                           nullptr).IsValid()))
        return false;
  }
  return true;
}

bool FQtCreatorSourceCodeAccessor::SaveAllOpenDocuments() const
{
  return false;
}

void FQtCreatorSourceCodeAccessor::Tick(const float DeltaTime)
{

}

#undef LOCTEXT_NAMESPACE
<commit_msg>Handling spaces in path names, removed my debug printf() statements<commit_after>/* Copyright (c) 2014 K. Ernest 'iFire' Lee

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */

// Add a class to handle the Solution file locally
// instead of relying on FDesktopPlatformModule.

#include "QtCreatorSourceCodeAccessPrivatePCH.h"
#include "QtCreatorSourceCodeAccessor.h"
#include "DesktopPlatformModule.h"

#define LOCTEXT_NAMESPACE "QtCreatorSourceCodeAccessor"
bool FQtCreatorSourceCodeAccessor::CanAccessSourceCode() const
{
  return FPaths::FileExists(TEXT("/usr/bin/clang"));
}

FName FQtCreatorSourceCodeAccessor::GetFName() const
{
  return FName("QtCreatorSourceCodeAccessor");
}

FText FQtCreatorSourceCodeAccessor::GetNameText() const
{
  return LOCTEXT("QtCreatorDisplayName", "Qt Creator");
}

FText FQtCreatorSourceCodeAccessor::GetDescriptionText() const
{
  return LOCTEXT("QtCreatorDisplayDesc", "Open source code files with Qt Creator");
}

bool FQtCreatorSourceCodeAccessor::OpenSolution()
{
  FString FullPath;
  FString SolutionFilenameWithoutExtension = TEXT("UE4");
  FString CodeSolutionFile = SolutionFilenameWithoutExtension + TEXT(".pro");

  if(FDesktopPlatformModule::Get()->GetSolutionPath(FullPath)){
    if ( FPaths::FileExists( FullPath ) )
    {
      FString Editor = FString(TEXT("/usr/bin/qtcreator"));
      FString Args = FString(TEXT("-client "));

      // Add this to handle spaces in path names.
      const FString NewFullPath = FString::Printf(TEXT("\"%s\""), *FullPath);

      Args.Append(NewFullPath);
      if(FLinuxPlatformProcess::CreateProc(*Editor,
                                           *Args,
                                           true,
                                           true,
                                           false,
                                           nullptr,
                                           0,
                                           nullptr,
                                           nullptr).IsValid())
      {
        return true;
      }
    }
  }
  return false;
}

bool FQtCreatorSourceCodeAccessor::OpenFileAtLine(const FString& FullPath, int32 LineNumber, int32 ColumnNumber)
{
    FString Editor = FString(TEXT("/usr/bin/qtcreator"));
    FString Args = FString(TEXT("-client "));

    // Add this to handle spaces in path names.
    const FString NewFullPath = FString::Printf(TEXT("\"%s:%d\""), *FullPath, LineNumber);

    Args.Append(NewFullPath); // .Append(TEXT(":")).Append(FString::FromInt(LineNumber));
    if (FLinuxPlatformProcess::CreateProc(*Editor,
                                          *Args,
                                          true,
                                          true,
                                          false,
                                          nullptr,
                                          0,
                                          nullptr,
                                          nullptr).IsValid())
    {
      return true;
    }

  return false;
}

bool FQtCreatorSourceCodeAccessor::OpenSourceFiles(const TArray<FString>& AbsoluteSourcePaths)
{
  for ( const FString& SourcePath : AbsoluteSourcePaths )
  {
      FString Editor = FString(TEXT("/usr/bin/qtcreator"));
      FString Args = FString(TEXT("-client "));

      // Add this to handle spaces in path names.
      const FString NewSourcePath = FString::Printf(TEXT("\"%s\""), *SourcePath);

      Args.Append(NewSourcePath);
      if(!(FLinuxPlatformProcess::CreateProc(*Editor,
                                             *Args,
                                             true,
                                             true,
                                             false,
                                             nullptr,
                                             0,
                                             nullptr,
                                             nullptr).IsValid()))
      {
          return false;
      }
  }

  return true;
}

bool FQtCreatorSourceCodeAccessor::SaveAllOpenDocuments() const
{
  return false;
}

void FQtCreatorSourceCodeAccessor::Tick(const float DeltaTime)
{

}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include <cassert>
//#include <osgDB/ReadFile>

#include "RenderToTextureStage.h"

//using namespace osg;
//using namespace osgUtil;

// register a RenderToTextureStage prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderToTextureStage> s_registerRenderToTextureStageProxy;

MyRenderToTextureStage::MyRenderToTextureStage()
{
    _pbuffer = 0L;
}

MyRenderToTextureStage::~MyRenderToTextureStage()
{
}

void MyRenderToTextureStage::reset()
{
    RenderStage::reset();
}

void MyRenderToTextureStage::draw(osg::State& state, osgUtil::RenderLeaf*& previous)
{
    if (_pbuffer && _texture.valid())
    {
        // Create pbuffer texture
        const unsigned int contextID = state.getContextID();
        GLuint& handle = _texture->getTextureObject(contextID);
        if (handle == 0)
        {
            // Create dynamic texture, subload callback required.
            _texture->apply(state);
        }

        HDC hdc = ::wglGetCurrentDC();
        HGLRC hglrc = ::wglGetCurrentContext();

        // Release pbuffer from "render to texture".
        _pbuffer->releaseTexImage();

        // Make the p-buffer's context current.
        _pbuffer->makeCurrent();

        // Render in p-buffer.
        RenderStage::draw(state,previous);

        // restore window's context as current.
        if (!::wglMakeCurrent(hdc, hglrc))
        {
            assert(0);
        }

        if (true /*_isRenderTextureSupported*/)
        {
            // transfer contents of p-buffer to texture
            _pbuffer->bindTexImage(handle);
        }
        else
        {
// TODO:
//          _pbuffer->copyTexImage(state);
        }

    }
    else
    {
        RenderStage::draw(state,previous);

        // now copy the rendered image to attached texture.
        if (_texture.valid())
            _texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());

        if (_image.valid())
            _image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),GL_RGBA,GL_UNSIGNED_BYTE);
    }
}
<commit_msg>Attempt to fix compile error caused by recent change in osg::Texture.<commit_after>#include <cassert>
//#include <osgDB/ReadFile>

#include "RenderToTextureStage.h"

//using namespace osg;
//using namespace osgUtil;

// register a RenderToTextureStage prototype with the RenderBin prototype list.
//RegisterRenderBinProxy<RenderToTextureStage> s_registerRenderToTextureStageProxy;

MyRenderToTextureStage::MyRenderToTextureStage()
{
    _pbuffer = 0L;
}

MyRenderToTextureStage::~MyRenderToTextureStage()
{
}

void MyRenderToTextureStage::reset()
{
    RenderStage::reset();
}

void MyRenderToTextureStage::draw(osg::State& state, osgUtil::RenderLeaf*& previous)
{
    if (_pbuffer && _texture.valid())
    {
        // Create pbuffer texture
        const unsigned int contextID = state.getContextID();
        osg::Texture::TextureObject* textureObeject = _texture->getTextureObject(contextID);
        if (textureObeject == 0)
        {
            // Create dynamic texture, subload callback required.
            _texture->apply(state);
        }

        HDC hdc = ::wglGetCurrentDC();
        HGLRC hglrc = ::wglGetCurrentContext();

        // Release pbuffer from "render to texture".
        _pbuffer->releaseTexImage();

        // Make the p-buffer's context current.
        _pbuffer->makeCurrent();

        // Render in p-buffer.
        RenderStage::draw(state,previous);

        // restore window's context as current.
        if (!::wglMakeCurrent(hdc, hglrc))
        {
            assert(0);
        }

        if (true /*_isRenderTextureSupported*/)
        {
            // transfer contents of p-buffer to texture
            _pbuffer->bindTexImage(textureObject->_id);
        }
        else
        {
// TODO:
//          _pbuffer->copyTexImage(state);
        }

    }
    else
    {
        RenderStage::draw(state,previous);

        // now copy the rendered image to attached texture.
        if (_texture.valid())
            _texture->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height());

        if (_image.valid())
            _image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),GL_RGBA,GL_UNSIGNED_BYTE);
    }
}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Touchable.cpp
 *  @brief  EC_Touchable enables visual effect for scene entity in cases where
 *          the entity can be considered to have some kind of functionality
 *          when it is clicked i.e. touched. The effect is not visible by default.
 *          You must call Show() function separately. The effect is visible only
 *          for certain time.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_Touchable.h"

#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
//#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <QApplication>
#include <QTimer>

#include "MemoryLeakCheck.h"

EC_Touchable::~EC_Touchable()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
        if (entityClone_)
            sceneMgr->destroyEntity(entityClone_);
    }
    else
    {
        entityClone_ = 0;
        sceneNode_ = 0;
    }
}

void EC_Touchable::Show()
{
    if (highlightOnHover.Get())
    {
        if (!entityClone_)
            Create();

        if (!entityClone_)
        {
            LogError("EC_Touchable not initialized properly.");
            return;
        }

        if (entityClone_ && sceneNode_)
            sceneNode_->getAttachedObject(cloneName_)->setVisible(true);
    }
}

void EC_Touchable::Hide()
{
    if (entityClone_ && sceneNode_)
        sceneNode_->getAttachedObject(cloneName_)->setVisible(false);
}

bool EC_Touchable::IsVisible() const
{
    if (entityClone_ && sceneNode_)
        return sceneNode_->getAttachedObject(cloneName_)->isVisible();
    return false;
}

EC_Touchable::EC_Touchable(IModule *module) :
    IComponent(module->GetFramework()),
    entityClone_(0),
    sceneNode_(0),
    materialName(this, "material name", "Touchable"),
    highlightOnHover(this, "highligh on hover", true),
    hoverCursor(this, "hover cursor", Qt::ArrowCursor)
{
    static AttributeMetadata metadata;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        metadata.enums[Qt::ArrowCursor] = "ArrowCursor";
        metadata.enums[Qt::UpArrow] = "UpArrowCursor";
        metadata.enums[Qt::CrossCursor] = "CrossCursor";
        metadata.enums[Qt::WaitCursor] = "WaitCursor";
        metadata.enums[Qt::IBeamCursor] = "IBeamCursor";
        metadata.enums[Qt::SizeVerCursor] = "SizeVerCursor";
        metadata.enums[Qt::SizeHorCursor] = "SizeHorCursor";
        metadata.enums[Qt::SizeBDiagCursor] = "SizeBDiagCursor";
        metadata.enums[Qt::SizeFDiagCursor] = "SizeFDiagCursor";
        metadata.enums[Qt::SizeAllCursor] = "SizeAllCursor";
        metadata.enums[Qt::BlankCursor] = "BlankCursor";
        metadata.enums[Qt::SplitVCursor] = "SplitVCursor";
        metadata.enums[Qt::SplitHCursor] = "SplitHCursor";
        metadata.enums[Qt::PointingHandCursor] = "PointingHandCursor";
        metadata.enums[Qt::ForbiddenCursor] = "ForbiddenCursor";
        metadata.enums[Qt::WhatsThisCursor] = "WhatsThisCursor";
        metadata.enums[Qt::BusyCursor] = "BusyCursor";
        metadata.enums[Qt::OpenHandCursor] = "OpenHandCursor";
        metadata.enums[Qt::ClosedHandCursor] = "ClosedHandCursor";
        metadataInitialized = true;
    }

    hoverCursor.SetMetadata(&metadata);

    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);
    connect(this, SIGNAL(OnChanged()), SLOT(UpdateMaterial()));
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
    connect(this, SIGNAL(ParentEntitySet()), SLOT(Create()));
}

void EC_Touchable::Create()
{
    if (renderer_.expired())
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;

    // Check out if this entity has EC_OgreMesh or EC_OgreCustomObject.
    Ogre::Entity *originalEntity  = 0;
    if (entity->GetComponent(OgreRenderer::EC_OgreMesh::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreMesh *ec_mesh= entity->GetComponent<OgreRenderer::EC_OgreMesh>().get();
        assert(ec_mesh);

        originalEntity = ec_mesh->GetEntity();
        sceneNode_ = ec_mesh->GetAdjustmentSceneNode();
    }
    else if(entity->GetComponent(OgreRenderer::EC_OgreCustomObject::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreCustomObject *ec_custom = entity->GetComponent<OgreRenderer::EC_OgreCustomObject>().get();
        assert(ec_custom);
        if (!ec_custom->IsCommitted())
        {
            LogError("Mesh entity have not been created for the target primitive. Cannot create EC_Touchable.");
            return;
        }

        originalEntity = ec_custom->GetEntity();
        sceneNode_ = placeable->GetSceneNode();
    }
    else
    {
        LogError("This entity doesn't have either EC_OgreMesh or EC_OgreCustomObject present. Cannot create EC_Touchable.");
        return;
    }

    assert(originalEntity && sceneNode_);
    if (!originalEntity || !sceneNode_)
        return;

    // Clone the Ogre entity.
    cloneName_ = std::string("entity") + renderer_.lock()->GetUniqueObjectName();
    entityClone_ = originalEntity->clone(cloneName_);
    assert(entityClone_);

    // Disable casting of shadows for the clone.
    entityClone_->setCastShadows(false);

    ///\todo If original entity has skeleton, (try to) link it to the clone.
/*
    if (originalEntity->hasSkeleton())
    {
        Ogre::SkeletonInstance *skel = originalEntity->getSkeleton();
        // If sharing a skeleton, force the attachment mesh to use the same skeleton
        // This is theoretically quite a scary operation, for there is possibility for things to go wrong
        Ogre::SkeletonPtr entity_skel = originalEntity->getMesh()->getSkeleton();
        if (entity_skel.isNull())
        {
            LogError("Cannot share skeleton for attachment, not found");
        }
        else
        {
            try
            {
                entityClone_->getMesh()->_notifySkeleton(entity_skel);
            }
            catch (Ogre::Exception &e)
            {
                LogError("Could not set shared skeleton for attachment: " + std::string(e.what()));
            }
        }
    }
*/

    try
    {
        //OgreRenderer::CloneMaterial("Touchable", materialName.Get());
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

    sceneNode_->attachObject(entityClone_);
    Hide();
}

void EC_Touchable::UpdateMaterial()
{
    if (!entityClone_ ||!sceneNode_)
        return;
    try
    {
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

//    hover_cursor_ = QCursor((Qt::CursorShape)(hoverCursor.Get()));
}

///\todo Remove this altogether. -jj. Integrate switching mouse cursors to input contexts so that
/// it is not possible to "miss" calling restoreOverrideCursor and leak a cursor to stay on screen. Releasing a context
/// also releases the cursor.
void EC_Touchable::SetCursorVisible(bool visible)
{
    if (hoverCursor.Get() != Qt::ArrowCursor)
    {
        QCursor *current_cursor = QApplication::overrideCursor();
        if (visible)
        {
            if (current_cursor)
            {
                if (current_cursor->shape() != hoverCursor.Get())
                    QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
            }
            else
                QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
        }
        else
        {
            while (current_cursor)
            {
                QApplication::restoreOverrideCursor();
                current_cursor = QApplication::overrideCursor();
            }
        }
    }
}

void EC_Touchable::OnHoverIn()
{
    LogInfo("OnHoverIn");
    SetCursorVisible(true);
    emit MouseHoverIn();
}

void EC_Touchable::OnHover()
{
    LogInfo("OnHover");
    if (!IsVisible())
        Show();
    emit MouseHover();
}

void EC_Touchable::OnHoverOut()
{
    LogInfo("OnHoverOut");
    if (IsVisible())
        Hide();

    SetCursorVisible(false);
    emit MouseHoverOut();
}

void EC_Touchable::OnClick()
{
    LogInfo("OnClick");
    emit MousePressed();
}

void EC_Touchable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        // Generic actions
        entity->ConnectAction("Show", this, SLOT(Show()));
        entity->ConnectAction("Hide", this, SLOT(Hide()));
        // Mouse actions
        entity->ConnectAction("MouseHover", this, SLOT(OnHover()));
        entity->ConnectAction("MouseHoverIn", this, SLOT(OnHoverIn()));
        entity->ConnectAction("MouseHoverOut", this, SLOT(OnHoverOut()));
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
    }
}

<commit_msg>Possible linux fix.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Touchable.cpp
 *  @brief  EC_Touchable enables visual effect for scene entity in cases where
 *          the entity can be considered to have some kind of functionality
 *          when it is clicked i.e. touched. The effect is not visible by default.
 *          You must call Show() function separately. The effect is visible only
 *          for certain time.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_Touchable.h"

#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
//#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <QApplication>
#include <QTimer>

#include "MemoryLeakCheck.h"

EC_Touchable::~EC_Touchable()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
        if (entityClone_)
            sceneMgr->destroyEntity(entityClone_);
    }
    else
    {
        entityClone_ = 0;
        sceneNode_ = 0;
    }
}

void EC_Touchable::Show()
{
    if (highlightOnHover.Get())
    {
        if (!entityClone_)
            Create();

        if (!entityClone_)
        {
            LogError("EC_Touchable not initialized properly.");
            return;
        }

        if (entityClone_ && sceneNode_)
            sceneNode_->getAttachedObject(cloneName_)->setVisible(true);
    }
}

void EC_Touchable::Hide()
{
    if (entityClone_ && sceneNode_)
        sceneNode_->getAttachedObject(cloneName_)->setVisible(false);
}

bool EC_Touchable::IsVisible() const
{
    if (entityClone_ && sceneNode_)
        return sceneNode_->getAttachedObject(cloneName_)->isVisible();
    return false;
}

EC_Touchable::EC_Touchable(IModule *module) :
    IComponent(module->GetFramework()),
    entityClone_(0),
    sceneNode_(0),
    materialName(this, "material name", "Touchable"),
    highlightOnHover(this, "highligh on hover", true),
    hoverCursor(this, "hover cursor", Qt::ArrowCursor)
{
    static AttributeMetadata metadata;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        metadata.enums[Qt::ArrowCursor] = "ArrowCursor";
        metadata.enums[Qt::UpArrow] = "UpArrowCursor";
        metadata.enums[Qt::CrossCursor] = "CrossCursor";
        metadata.enums[Qt::WaitCursor] = "WaitCursor";
        metadata.enums[Qt::IBeamCursor] = "IBeamCursor";
        metadata.enums[Qt::SizeVerCursor] = "SizeVerCursor";
        metadata.enums[Qt::SizeHorCursor] = "SizeHorCursor";
        metadata.enums[Qt::SizeBDiagCursor] = "SizeBDiagCursor";
        metadata.enums[Qt::SizeFDiagCursor] = "SizeFDiagCursor";
        metadata.enums[Qt::SizeAllCursor] = "SizeAllCursor";
        metadata.enums[Qt::BlankCursor] = "BlankCursor";
        metadata.enums[Qt::SplitVCursor] = "SplitVCursor";
        metadata.enums[Qt::SplitHCursor] = "SplitHCursor";
        metadata.enums[Qt::PointingHandCursor] = "PointingHandCursor";
        metadata.enums[Qt::ForbiddenCursor] = "ForbiddenCursor";
        metadata.enums[Qt::WhatsThisCursor] = "WhatsThisCursor";
        metadata.enums[Qt::BusyCursor] = "BusyCursor";
        metadata.enums[Qt::OpenHandCursor] = "OpenHandCursor";
        metadata.enums[Qt::ClosedHandCursor] = "ClosedHandCursor";
        metadataInitialized = true;
    }

    hoverCursor.SetMetadata(&metadata);

    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);
    connect(this, SIGNAL(OnChanged()), SLOT(UpdateMaterial()));
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
//    connect(this, SIGNAL(ParentEntitySet()), SLOT(Create()));
}

void EC_Touchable::Create()
{
    if (renderer_.expired())
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;

    // Check out if this entity has EC_OgreMesh or EC_OgreCustomObject.
    Ogre::Entity *originalEntity  = 0;
    if (entity->GetComponent(OgreRenderer::EC_OgreMesh::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreMesh *ec_mesh= entity->GetComponent<OgreRenderer::EC_OgreMesh>().get();
        assert(ec_mesh);

        originalEntity = ec_mesh->GetEntity();
        sceneNode_ = ec_mesh->GetAdjustmentSceneNode();
    }
    else if(entity->GetComponent(OgreRenderer::EC_OgreCustomObject::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreCustomObject *ec_custom = entity->GetComponent<OgreRenderer::EC_OgreCustomObject>().get();
        assert(ec_custom);
        if (!ec_custom->IsCommitted())
        {
            LogError("Mesh entity have not been created for the target primitive. Cannot create EC_Touchable.");
            return;
        }

        originalEntity = ec_custom->GetEntity();
        sceneNode_ = placeable->GetSceneNode();
    }
    else
    {
        LogError("This entity doesn't have either EC_OgreMesh or EC_OgreCustomObject present. Cannot create EC_Touchable.");
        return;
    }

    assert(originalEntity && sceneNode_);
    if (!originalEntity || !sceneNode_)
        return;

    // Clone the Ogre entity.
    cloneName_ = std::string("entity") + renderer_.lock()->GetUniqueObjectName();
    entityClone_ = originalEntity->clone(cloneName_);
    assert(entityClone_);

    // Disable casting of shadows for the clone.
    entityClone_->setCastShadows(false);

    ///\todo If original entity has skeleton, (try to) link it to the clone.
/*
    if (originalEntity->hasSkeleton())
    {
        Ogre::SkeletonInstance *skel = originalEntity->getSkeleton();
        // If sharing a skeleton, force the attachment mesh to use the same skeleton
        // This is theoretically quite a scary operation, for there is possibility for things to go wrong
        Ogre::SkeletonPtr entity_skel = originalEntity->getMesh()->getSkeleton();
        if (entity_skel.isNull())
        {
            LogError("Cannot share skeleton for attachment, not found");
        }
        else
        {
            try
            {
                entityClone_->getMesh()->_notifySkeleton(entity_skel);
            }
            catch (Ogre::Exception &e)
            {
                LogError("Could not set shared skeleton for attachment: " + std::string(e.what()));
            }
        }
    }
*/

    try
    {
        //OgreRenderer::CloneMaterial("Touchable", materialName.Get());
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

    sceneNode_->attachObject(entityClone_);
    Hide();
}

void EC_Touchable::UpdateMaterial()
{
    if (!entityClone_ ||!sceneNode_)
        return;
    try
    {
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

//    hover_cursor_ = QCursor((Qt::CursorShape)(hoverCursor.Get()));
}

///\todo Remove this altogether. -jj. Integrate switching mouse cursors to input contexts so that
/// it is not possible to "miss" calling restoreOverrideCursor and leak a cursor to stay on screen. Releasing a context
/// also releases the cursor.
void EC_Touchable::SetCursorVisible(bool visible)
{
    if (hoverCursor.Get() != Qt::ArrowCursor)
    {
        QCursor *current_cursor = QApplication::overrideCursor();
        if (visible)
        {
            if (current_cursor)
            {
                if (current_cursor->shape() != hoverCursor.Get())
                    QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
            }
            else
                QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
        }
        else
        {
            while (current_cursor)
            {
                QApplication::restoreOverrideCursor();
                current_cursor = QApplication::overrideCursor();
            }
        }
    }
}

void EC_Touchable::OnHoverIn()
{
    LogInfo("OnHoverIn");
    SetCursorVisible(true);
    emit MouseHoverIn();
}

void EC_Touchable::OnHover()
{
    LogInfo("OnHover");
    if (!IsVisible())
        Show();
    emit MouseHover();
}

void EC_Touchable::OnHoverOut()
{
    LogInfo("OnHoverOut");
    if (IsVisible())
        Hide();

    SetCursorVisible(false);
    emit MouseHoverOut();
}

void EC_Touchable::OnClick()
{
    LogInfo("OnClick");
    emit MousePressed();
}

void EC_Touchable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        // Generic actions
        entity->ConnectAction("Show", this, SLOT(Show()));
        entity->ConnectAction("Hide", this, SLOT(Hide()));
        // Mouse actions
        entity->ConnectAction("MouseHover", this, SLOT(OnHover()));
        entity->ConnectAction("MouseHoverIn", this, SLOT(OnHoverIn()));
        entity->ConnectAction("MouseHoverOut", this, SLOT(OnHoverOut()));
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
    }
}

<|endoftext|>