diff --git a/src/effects/ConeWave.cpp b/src/effects/ConeWave.cpp index 139ec387..cea46eef 100644 --- a/src/effects/ConeWave.cpp +++ b/src/effects/ConeWave.cpp @@ -66,10 +66,10 @@ void ConeWave::Render(double dt) { void ConeWave::InitGeode() { CreateTexturedCone(this); - //getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - //getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); - //getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); - //setCullingActive(false); + getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); + getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + setCullingActive(false); } void ConeWave::Destory() { diff --git a/src/entities/ComponentFactory.cpp b/src/entities/ComponentFactory.cpp index 0934d666..08e7f2cf 100644 --- a/src/entities/ComponentFactory.cpp +++ b/src/entities/ComponentFactory.cpp @@ -9,6 +9,7 @@ #include "entities/ChaffBombsComponent.h" #include "entities/ConeWaveComponent.h" #include "entities/DashedLineComponent.h" +#include "entities/LabelComponent.h" //Component::Component(QObject* parent) // : QObject(parent) { @@ -36,6 +37,8 @@ SceneComponent* ComponentFactory::Create(const QString& name, SceneComponent* pa return new ConeWaveComponent(parenet); } else if ("DashedLineComponent" == name) { return new DashedLineComponent(parenet); + } else if ("LabelComponent" == name) { + return new LabelComponent(parenet); } return nullptr; } diff --git a/src/entities/LabelComponent.cpp b/src/entities/LabelComponent.cpp new file mode 100644 index 00000000..26b9486e --- /dev/null +++ b/src/entities/LabelComponent.cpp @@ -0,0 +1,184 @@ +#include "entities/LabelComponent.h" + +#include +#include +#include +#include +#include + +#include "entities/Entity.h" +#include "common/SpdLogger.h" + +LabelComponent::LabelComponent(SceneComponent* parent) + : SceneComponent(parent) + , text_("Label") + , fontSize_(16.0f) + , color_(1.0f, 1.0f, 1.0f, 1.0f) + , visible_(true) + , needUpdate_(true) { +} + +LabelComponent::~LabelComponent() { +} + +std::string LabelComponent::GetTypeName() { + return "LabelComponent"; +} + +void LabelComponent::AttachEntity(Entity* entity) { + SceneComponent::AttachEntity(entity); + + if (entity && !entity->GetName().isEmpty()) { + LOG_INFO("LabelComponent: Attaching to entity '{}'", entity->GetName().toUtf8().data()); + SetText(entity->GetName().toLocal8Bit().data()); + + Entity* entity = GetEntity(); + if (nullptr != entity) { + connect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText); + } + + CreateTextNode(); + } +} + +bool LabelComponent::SetAttribute(const char* name, const char* value) { + if (0 == strcmp(name, "text")) { + SetText(value); + return true; + } else if (0 == strcmp(name, "fontSize")) { + SetFontSize(static_cast(atof(value))); + return true; + } else if (0 == strcmp(name, "visible")) { + SetVisible(0 == strcmp(value, "true")); + return true; + } else if (0 == strcmp(name, "color")) { + float r, g, b, a = 1.0f; + int parsed = sscanf(value, "%f,%f,%f,%f", &r, &g, &b, &a); + if (parsed >= 3) { + SetColor(osg::Vec4(r, g, b, a)); + return true; + } + } + + return SceneComponent::SetAttribute(name, value); +} + +bool LabelComponent::SaveAttribute(tinyxml2::XMLElement* element) { + element->SetAttribute("text", text_.c_str()); + element->SetAttribute("fontSize", fontSize_); + element->SetAttribute("visible", visible_ ? "true" : "false"); + + // 保存颜色 + char colorStr[64]; + sprintf(colorStr, "%.2f,%.2f,%.2f,%.2f", color_.r(), color_.g(), color_.b(), color_.a()); + element->SetAttribute("color", colorStr); + + return SceneComponent::SaveAttribute(element); +} + +std::string LabelComponent::GetSelfTypeName() { + return LabelComponent::GetTypeName(); +} + +void LabelComponent::Begin() { + SceneComponent::Begin(); + + +} + +void LabelComponent::Update(double dt) { + SceneComponent::Update(dt); + + if (needUpdate_) { + UpdateTextNode(); + needUpdate_ = false; + } +} + +void LabelComponent::End() { + SceneComponent::End(); + + Entity* entity = GetEntity(); + if (nullptr != entity) { + disconnect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText); + } +} + +void LabelComponent::AddToRender() { + SceneComponent::AddToRender(); +} + +void LabelComponent::SetText(const std::string& text) { + if (text_ != text) { + text_ = text; + needUpdate_ = true; + } +} + +void LabelComponent::SetFontSize(float size) { + if (fontSize_ != size) { + fontSize_ = size; + needUpdate_ = true; + } +} + +void LabelComponent::SetColor(const osg::Vec4& color) { + if (color_ != color) { + color_ = color; + needUpdate_ = true; + } +} + +void LabelComponent::SetVisible(bool visible) { + if (visible_ != visible) { + visible_ = visible; + if (textGeode_.valid()) { + textGeode_->setNodeMask(visible_ ? 0xffffffff : 0x0); + } + } +} + +void LabelComponent::CreateTextNode() { + if (!textGeode_.valid()) { + textGeode_ = new osg::Geode(); + textNode_ = new osgText::Text(); + + textNode_->setAlignment(osgText::Text::CENTER_CENTER); + textNode_->setAxisAlignment(osgText::Text::SCREEN); + textNode_->setCharacterSizeMode(osgText::Text::SCREEN_COORDS); + textNode_->setText(text_); + + textGeode_->addDrawable(textNode_.get()); + + osg::StateSet* stateSet = textGeode_->getOrCreateStateSet(); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF); + stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + stateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + + osg::ref_ptr mt = new osg::MatrixTransform(); + mt->addChild(textGeode_); + if (!mt_.valid()) { + mt_ = mt; + } + + needUpdate_ = true; + } +} + +void LabelComponent::UpdateTextNode() { + if (textNode_.valid()) { + textNode_->setText(text_); + textNode_->setCharacterSize(fontSize_); + textNode_->setColor(color_); + + textNode_->setPosition(osg::Vec3(0.0f, 0.0f, 0.0f)); + + SPDLOG_INFO("LabelComponent: Updated text '{}' with size {}", text_, fontSize_); + } +} + +void LabelComponent::UpdateText(const QString& text) { + SetText(text.toLocal8Bit().data()); + needUpdate_ = true; +} diff --git a/src/entities/LabelComponent.h b/src/entities/LabelComponent.h new file mode 100644 index 00000000..26891c75 --- /dev/null +++ b/src/entities/LabelComponent.h @@ -0,0 +1,57 @@ +#pragma once + +#include "entities/SceneComponent.h" + +#include + +#include +#include +#include + +class LabelComponent : public SceneComponent { + Q_OBJECT + +public: + explicit LabelComponent(SceneComponent* parent = nullptr); + ~LabelComponent(); + + static std::string GetTypeName(); + + void AttachEntity(class Entity* owner) override; + bool SetAttribute(const char* name, const char* value) override; + bool SaveAttribute(tinyxml2::XMLElement* element) override; + std::string GetSelfTypeName() override; + + void Begin() override; + void Update(double dt) override; + void End() override; + void AddToRender() override; + + // 标签相关方法 + void SetText(const std::string& text); + const std::string& GetText() const { return text_; } + + void SetFontSize(float size); + float GetFontSize() const { return fontSize_; } + + void SetColor(const osg::Vec4& color); + const osg::Vec4& GetColor() const { return color_; } + + void SetVisible(bool visible); + bool IsVisible() const { return visible_; } + +protected: + void CreateTextNode(); + void UpdateTextNode(); + void UpdateText(const QString& text); + +protected: + std::string text_; + float fontSize_; + osg::Vec4 color_; + bool visible_; + bool needUpdate_; + + osg::ref_ptr textGeode_; + osg::ref_ptr textNode_; +}; \ No newline at end of file diff --git a/src/entities/SceneComponent.h b/src/entities/SceneComponent.h index 952347cb..a6999e69 100644 --- a/src/entities/SceneComponent.h +++ b/src/entities/SceneComponent.h @@ -1,5 +1,6 @@ #pragma once +#include #include "entities/Component.h" //#include "entities/Entity.h" #include "utils/Transform.h"