3 #include <BLIB/Engine.hpp>
17 bool pipelinesCreated =
false;
19 using CustomBindings =
20 bl::rc::ds::Bindings<bl::rc::ds::GlobalUniformBuffer<ConversationTreeComponent::TreeCamera>>;
21 using CustomSet = bl::rc::ds::GenericDescriptorSetInstance<CustomBindings>;
22 using CustomSetFactory =
23 bl::rc::ds::GenericDescriptorSetFactory<CustomBindings, VK_SHADER_STAGE_VERTEX_BIT>;
25 void ensurePipelinesCreated(bl::engine::Engine& engine) {
26 if (!pipelinesCreated) {
27 pipelinesCreated =
true;
29 auto& cache = engine.renderer().pipelineCache();
31 bl::rc::vk::PipelineParameters()
32 .withPrimitiveType(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
33 .withSimpleDepthStencil(
true)
34 .addDescriptorSet<bl::rc::ds::TexturePoolFactory>()
35 .addDescriptorSet<bl::rc::ds::Scene2DFactory>()
36 .addDescriptorSet<bl::rc::ds::Object2DFactory>()
37 .addDescriptorSet<CustomSetFactory>()
38 .withShaders(
"Resources/Shaders/Editor/conversationTree.vert.spv",
39 bl::rc::Config::ShaderIds::Fragment2DUnlit)
42 bl::rc::vk::PipelineParameters()
43 .withPrimitiveType(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
44 .withSimpleDepthStencil(
true)
45 .addDescriptorSet<bl::rc::ds::TexturePoolFactory>()
46 .addDescriptorSet<bl::rc::ds::Scene2DFactory>()
47 .addDescriptorSet<bl::rc::ds::Object2DFactory>()
48 .addDescriptorSet<CustomSetFactory>()
49 .withShaders(
"Resources/Shaders/Editor/conversationTree.vert.spv",
50 bl::rc::Config::ShaderIds::TextFragment)
55 const sf::Color NodeColor(80, 90, 230);
56 const sf::Color TerminatorColor(230, 70, 120);
57 const sf::Color SelectedNodeColor(190, 190, 70);
58 const sf::Color DownArrowColor(30, 220, 65);
59 const sf::Color UpArrowColor(230, 90, 40);
61 constexpr
float ArrowWidth = 24.f;
62 constexpr
float ArrowDepth = 18.f;
67 : Component(HighlightState::IgnoresMouse)
69 , currentOverlay(nullptr)
70 , lastTreeVersion(std::numeric_limits<unsigned int>::max())
73 void ConversationTreeComponent::setVisible(
bool visible) { background.setHidden(!visible); }
75 void ConversationTreeComponent::onElementUpdated() {
76 auto& tree = getOwnerAs<ConversationTree>();
79 if (lastTreeVersion != tree.getTreeVersion()) {
80 lastTreeVersion = tree.getTreeVersion();
83 nodeCircles.resize(tree.getNodes().size());
84 nodeLabels.resize(tree.getNodes().size());
86 for (
auto& src : tree.getNodes()) {
87 auto& circle = nodeCircles[i];
88 if (!circle.isCreated()) {
92 circle.setFillColor(NodeColor);
94 circle.getLocalTransform().setPosition(src.center);
96 auto& lbl = nodeLabels[i];
98 lbl = std::make_unique<bl::gfx::Text>();
99 lbl->create(*enginePtr,
104 sf::Text::Style::Bold);
105 lbl->setParent(shapeBatch);
106 if (currentOverlay) {
107 lbl->addToSceneWithCustomPipeline(
109 bl::rc::UpdateSpeed::Static,
113 else { lbl->getSection().setString(src.label); }
117 bl::com::Transform2D transform;
118 transform.setOrigin(lbl->getLocalSize() * 0.5f);
119 transform.setPosition(src.center);
120 for (
auto& v : lbl->component().vertices.vertices()) {
121 v.pos = transform.transformPoint(v.pos);
123 lbl->getTransform().setPosition(shapeBatch.getTransform().getLocalPosition());
129 constexpr
float SrcSize = 25.f;
130 nodeArrows.resize(tree.getEdges().size(),
131 bl::gfx::BatchIcon(bl::gfx::BatchIcon::Type::Arrow, {SrcSize, SrcSize}));
133 for (
auto& src : tree.getEdges()) {
134 auto& arrow = nodeArrows[i];
137 if (!arrow.isCreated()) { arrow.create(*enginePtr, shapeBatch); }
139 const auto& from = tree.getNodes()[src.from];
140 const auto& to = tree.getNodes()[src.to];
142 const glm::vec2 pdiff = to.center - from.center;
144 const float angle = atan2f(pdiff.y, pdiff.x);
145 const float degrees = bl::math::radiansToDegrees(angle) + 90.f;
146 arrow.setSize({ArrowWidth, gap});
147 arrow.getLocalTransform().setOrigin(arrow.getSize() * 0.5f);
148 arrow.getLocalTransform().setPosition(from.center + pdiff * 0.5f);
149 arrow.getLocalTransform().setRotation(degrees);
150 arrow.setFillColor(src.to > src.from ? DownArrowColor : UpArrowColor);
155 const auto* srcNode = &tree.getNodes()[0];
157 for (
auto& node : nodeCircles) {
158 sf::Color col = srcNode->terminator ? TerminatorColor : NodeColor;
159 if (tree.shouldHighlightSelectedNode() && i == tree.getSelectedNode()) {
160 col = SelectedNodeColor;
162 const glm::vec4 gcol = bl::sfcol(col);
163 if (gcol != node.getFillColor()) { node.setFillColor(gcol); }
170 uniform->
center = tree.getCamCenter();
171 uniform->
zoom = tree.getCamZoom();
172 uniform->
acqSize.x = tree.getAcquisition().width;
173 uniform->
acqSize.y = tree.getAcquisition().height;
177 void ConversationTreeComponent::onRenderSettingChange() {}
179 bl::ecs::Entity ConversationTreeComponent::getEntity()
const {
return background.entity(); }
181 void ConversationTreeComponent::doCreate(bl::engine::Engine& engine, bl::gui::rdr::Renderer&) {
183 ensurePipelinesCreated(engine);
185 background.create(engine, {100.f, 100.f});
186 background.setFillColor(sf::Color::Cyan);
187 background.setOutlineColor(sf::Color::Black);
188 background.setOutlineThickness(-2.f);
189 background.getOverlayScaler().setScissorMode(bl::com::OverlayScaler::ScissorSelfConstrained);
191 shapeBatch.create(engine, 2048);
192 shapeBatch.setParent(background);
195 void ConversationTreeComponent::doSceneAdd(bl::rc::Overlay* overlay) {
196 currentOverlay = overlay;
198 background.addToScene(overlay, bl::rc::UpdateSpeed::Static);
199 shapeBatch.addToSceneWithCustomPipeline(
201 bl::rc::UpdateSpeed::Static,
203 for (
auto& label : nodeLabels) {
204 label->addToSceneWithCustomPipeline(overlay,
205 bl::rc::UpdateSpeed::Static,
209 uniform = &overlay->getDescriptorSet<CustomSet>().getBindingPayload<TreeCamera>();
212 void ConversationTreeComponent::doSceneRemove() { background.removeFromScene(); }
214 void ConversationTreeComponent::handleAcquisition() {
215 const auto& acq = getOwnerAs<ConversationTree>().getAcquisition();
216 background.setSize({acq.width, acq.height});
219 uniform->
acqSize.x = acq.width;
220 uniform->
acqSize.y = acq.height;
224 void ConversationTreeComponent::handleMove() {
225 const auto pos = getOwnerAs<ConversationTree>().getLocalPosition();
226 background.getTransform().setPosition(pos.x, pos.y);
All classes and functionality used for implementing the game editor.
static const sf::VulkanFont & MenuFont()
static constexpr std::uint32_t EditorConversationTreeTextPipelineId
static constexpr std::uint32_t EditorConversationTreeShapePipelineId
static constexpr float NodeRadius
ConversationTreeComponent()
Creates the component.