Skip to content

Commit

Permalink
Merge pull request #57 from PipeRift/feature/graph-context-improvements
Browse files Browse the repository at this point in the history
Graph context menu improvements
  • Loading branch information
muit authored May 1, 2022
2 parents 3dd2f69 + 156f0de commit edff67c
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 273 deletions.
8 changes: 4 additions & 4 deletions CMake/LLVM.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}")
message(STATUS "LLVM_DEFINITIONS: ${LLVM_DEFINITIONS_LIST}")


add_library(LLVM INTERFACE)
target_include_directories(LLVM INTERFACE ${LLVM_INCLUDE_DIRS})
add_library(RiftLLVM INTERFACE)
target_include_directories(RiftLLVM INTERFACE ${LLVM_INCLUDE_DIRS})
llvm_map_components_to_libnames(llvm_libs core x86asmparser x86codegen)
target_link_libraries(LLVM INTERFACE ${LLVM_AVAILABLE_LIBS})
target_compile_definitions(LLVM INTERFACE ${LLVM_DEFINITIONS_LIST} -DNOMINMAX)
target_link_libraries(RiftLLVM INTERFACE ${LLVM_AVAILABLE_LIBS})
target_compile_definitions(RiftLLVM INTERFACE ${LLVM_DEFINITIONS_LIST} -DNOMINMAX)
# rift_target_disable_all_warnings(LLVM INTERFACE)

2 changes: 1 addition & 1 deletion Libs/Backends/LLVM/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rift_target_shared_output_directory(RiftBackendLLVM)

target_link_libraries(RiftBackendLLVM PUBLIC Rift::Rift)

target_link_libraries(RiftBackendLLVM PRIVATE LLVM)
target_link_libraries(RiftBackendLLVM PRIVATE RiftLLVM)


install(TARGETS RiftBackendLLVM
Expand Down
4 changes: 1 addition & 3 deletions Libs/Editor/Include/Utils/FunctionGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace Rift::Graph

float GetSpaceHeight(u32 height) const;
v2 GetContentPadding() const;
v2 GetGridPosition(v2 screenPosition) const;
};
inline Settings settings{};

Expand All @@ -46,16 +47,13 @@ namespace Rift::Graph
void Init();
void Shutdown();


void PushNodeStyle();
void PopNodeStyle();
void PushInnerNodeStyle();
void PopInnerNodeStyle();

void DrawContextMenu(AST::Tree& ast);
void DrawTypeGraph(AST::Tree& ast, AST::Id typeId, CTypeEditor& typeEditor);

v2 GetGridPosition(v2 screenPosition);
void SetNodePosition(AST::Id id, v2 position);
v2 GetNodePosition(AST::Id id);

Expand Down
11 changes: 11 additions & 0 deletions Libs/Editor/Include/Utils/FunctionGraphContextMenu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2015-2022 Piperift - All rights reserved
#pragma once

#include <AST/Filtering.h>
#include <AST/Tree.h>


namespace Rift::Graph
{
void DrawContextMenu(AST::Tree& ast, AST::Id typeId, AST::Id hoveredNodeId);
} // namespace Rift::Graph
7 changes: 4 additions & 3 deletions Libs/Editor/Include/Utils/Nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,15 +439,16 @@ namespace Rift::Nodes
// Use the following functions to query a change of state for an existing link, or new link.
// Call these after EndNodeEditor().

// Did the user start dragging a new link from a pin?
bool IsLinkStarted(Id* outputPinId);
bool IsDraggingLink();
TPair<Id, PinType> GetDraggedOriginPin();
// Did the user drop the dragged link before attaching it to a pin?
// There are two different kinds of situations to consider when handling this event:
// 1) a link which is created at a pin and then dropped
// 2) an existing link which is detached from a pin and then dropped
// Use the including_detached_links flag to control whether this function triggers when the
// user detaches a link and drops it.
bool IsLinkDropped(Id* outputPinId = nullptr, bool includingDetachedLinks = true);
bool IsLinkDropped(
Id* outputId = nullptr, Id* inputId = nullptr, bool includingDetachedLinks = true);
// Did the user finish creating a new link?
bool IsLinkCreated(Id& outputPinId, Id& inputPinId, bool* createdFromSnap = nullptr);
bool IsLinkCreated(AST::Id& outputNodeId, Id& outputPinId, AST::Id& inputNodeId, Id& inputPinId,
Expand Down
2 changes: 1 addition & 1 deletion Libs/Editor/Include/Utils/NodesInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ namespace Rift::Nodes

T& Get(AST::Id id)
{
Check(Contains(id));
return *GetByIndex(AST::GetIndex(id));
}

Expand Down Expand Up @@ -186,6 +185,7 @@ namespace Rift::Nodes
private:
T* GetByIndex(u32 index)
{
Check(data.IsValidIndex(index));
return data.Data() + index;
}
};
Expand Down
242 changes: 12 additions & 230 deletions Libs/Editor/Src/Utils/FunctionGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#include "Components/CTypeEditor.h"
#include "DockSpaceLayout.h"
#include "Utils/EditorStyle.h"
#include "Utils/FunctionGraphContextMenu.h"
#include "Utils/FunctionUtils.h"
#include "Utils/TypeUtils.h"

#include <AST/Components/CDeclFunction.h>
#include <AST/Components/CDeclVariable.h>
Expand All @@ -26,9 +26,9 @@
#include <AST/Components/CStmtInput.h>
#include <AST/Components/CStmtOutputs.h>
#include <AST/Components/CStmtReturn.h>
#include <AST/Components/CType.h>
#include <AST/Components/Views/CGraphTransform.h>
#include <AST/Filtering.h>
#include <AST/Statics/STypes.h>
#include <AST/Utils/Expressions.h>
#include <AST/Utils/Hierarchy.h>
#include <AST/Utils/Statements.h>
Expand Down Expand Up @@ -71,6 +71,11 @@ namespace Rift::Graph
return {0.f, settings.verticalMargin + settings.verticalPadding};
}

v2 Settings::GetGridPosition(v2 screenPosition) const
{
return Nodes::ScreenToGridPosition(screenPosition) * GetInvGridSize();
}

void BeginNode(TAccessRef<TWrite<CGraphTransform>> access, AST::Id id)
{
currentNodeTransform = &access.GetOrAdd<CGraphTransform>(id);
Expand Down Expand Up @@ -465,223 +470,6 @@ namespace Rift::Graph
{
ImGui::PopStyleVar(2);
}
void DrawNodeContextMenu(AST::Tree& ast, AST::Id typeId, TSpan<AST::Id> nodeIds)
{
Check(!nodeIds.IsEmpty());

AST::Id firstNodeId = nodeIds[0];

if (nodeIds.Size() == 1 && ast.Has<CDeclFunction>(firstNodeId))
{
if (UI::MenuItem("Add return node"))
{
AST::Id newId = Functions::AddReturn({ast, typeId});
if (!IsNone(newId))
{
v2 position = ast.Get<CGraphTransform>(firstNodeId).position;
ast.Add<CGraphTransform>(newId, position + v2{10.f, 0.f});

AST::Statements::TryConnect(ast, firstNodeId, newId);
}
}
UI::Separator();
}
if (UI::MenuItem("Delete"))
{
Functions::RemoveNodes(ast, nodeIds);
}
}

void DrawGraphContextMenu(AST::Tree& ast, AST::Id typeId)
{
static ImGuiTextFilter filter;
if (UI::IsWindowAppearing())
{
UI::SetKeyboardFocusHere();
}
filter.Draw("##Filter");
const v2 clickPos = UI::GetMousePosOnOpeningCurrentPopup();
const v2 gridPos = GetGridPosition(clickPos).Floor();

if (filter.IsActive() || UI::TreeNode("Flow"))
{
if (filter.PassFilter("Return") && UI::MenuItem("Return"))
{
AST::Id newId = Functions::AddReturn({ast, typeId});
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
if (filter.PassFilter("If") && UI::MenuItem("If"))
{
AST::Id newId = Functions::AddIf({ast, typeId});
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}

if (!filter.IsActive())
{
UI::TreePop();
}
}

if (filter.IsActive() || UI::TreeNode("Operators"))
{
static String name;
// Unary operators
for (auto type : Refl::GetEnumValues<UnaryOperatorType>())
{
StringView shortName = Functions::GetUnaryOperatorName(type);
StringView longName = Functions::GetUnaryOperatorLongName(type);
name.clear();
Strings::FormatTo(name, "{} ({})", shortName, longName);
if (filter.PassFilter(name.data(), name.data() + name.size())
&& UI::MenuItem(name.data()))
{
AST::Id newId = Functions::AddUnaryOperator({ast, typeId}, type);
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
}
// Binary operators
for (auto type : Refl::GetEnumValues<BinaryOperatorType>())
{
StringView shortName = Functions::GetBinaryOperatorName(type);
StringView longName = Functions::GetBinaryOperatorLongName(type);
name.clear();
Strings::FormatTo(name, "{} ({})", shortName, longName);
if (filter.PassFilter(name.data(), name.data() + name.size())
&& UI::MenuItem(name.data()))
{
AST::Id newId = Functions::AddBinaryOperator({ast, typeId}, type);
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
}

if (!filter.IsActive())
{
UI::TreePop();
}
}

if (filter.IsActive() || UI::TreeNode("Constructors"))
{
String makeStr{};
auto& typeList = ast.GetStatic<STypes>();
auto types = ast.Filter<CType>();
for (const auto& it : typeList.typesByName)
{
if (auto* type = types.TryGet<CType>(it.second))
{
makeStr.clear();
Strings::FormatTo(makeStr, "Make {}", type->name);
if (filter.PassFilter(makeStr.c_str(), makeStr.c_str() + makeStr.size()))
{
if (UI::MenuItem(makeStr.c_str()))
{
AST::Id newId = Functions::AddLiteral({ast, typeId}, it.second);
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
}
}
}

if (!filter.IsActive())
{
UI::TreePop();
}
}

if (filter.IsActive() || UI::TreeNode("Variables"))
{
auto variables = ast.Filter<CDeclVariable>();
auto identifiers = ast.Filter<CIdentifier>();
for (AST::Id variableId : variables)
{
if (auto* iden = identifiers.TryGet<CIdentifier>(variableId))
{
const String& name = iden->name.ToString();
if (filter.PassFilter(name.c_str(), name.c_str() + name.size()))
{
if (UI::MenuItem(name.c_str()))
{
AST::Id newId =
Functions::AddDeclarationReference({ast, typeId}, variableId);
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
}
}
}

if (!filter.IsActive())
{
UI::TreePop();
}
}

if (filter.IsActive() || UI::TreeNode("Functions"))
{
auto functions = ast.Filter<CDeclFunction>();
auto identifiers = ast.Filter<CIdentifier>();
for (AST::Id functionId : functions)
{
if (auto* iden = identifiers.TryGet<CIdentifier>(functionId))
{
const String& name = iden->name.ToString();
if (filter.PassFilter(name.c_str(), name.c_str() + name.size()))
{
if (UI::MenuItem(name.c_str()))
{
AST::Id newId = Functions::AddCall({ast, typeId}, functionId);
if (!IsNone(newId))
{
ast.Add<CGraphTransform>(newId, gridPos);
}
}
}
}
}

if (!filter.IsActive())
{
ImGui::TreePop();
}
}
}

void DrawContextMenu(AST::Tree& ast, AST::Id typeId, AST::Id hoveredNodeId)
{
if (ImGui::BeginPopup("GraphContextMenu"))
{
if (IsNone(hoveredNodeId))
{
DrawGraphContextMenu(ast, typeId);
}
else if (Nodes::IsNodeSelected(hoveredNodeId))
{
DrawNodeContextMenu(ast, typeId, Nodes::GetSelectedNodes());
}
else
{
DrawNodeContextMenu(ast, typeId, hoveredNodeId);
}
ImGui::EndPopup();
}
}

void DrawFunctionDecls(AST::Tree& ast, const TArray<AST::Id>& functionDecls)
{
Expand Down Expand Up @@ -1065,15 +853,15 @@ namespace Rift::Graph
// Links
DrawStatementLinks(ast, *children);
DrawExpressionLinks(ast, *children);

if (UI::IsKeyReleased(GLFW_KEY_DELETE))
{
Functions::RemoveNodes(ast, Nodes::GetSelectedNodes());
}
}

Nodes::DrawMiniMap(0.2f, Nodes::MiniMapCorner::TopRight);
PopNodeStyle();

if (UI::IsKeyReleased(GLFW_KEY_DELETE))
{
Functions::RemoveNodes(ast, Nodes::GetSelectedNodes());
}
Nodes::EndNodeEditor();

Nodes::Id outputPin;
Expand Down Expand Up @@ -1102,12 +890,6 @@ namespace Rift::Graph
}
}


v2 GetGridPosition(v2 screenPosition)
{
return Nodes::ScreenToGridPosition(screenPosition) * settings.GetInvGridSize();
}

void SetNodePosition(AST::Id id, v2 position)
{
position *= settings.GetGridSize();
Expand Down
Loading

0 comments on commit edff67c

Please sign in to comment.