vn/code/vn_workspace_editor.cpp

233 lines
7.2 KiB
C++

//- sixten: Managing nodes
static workspace_editor_node *Workspace_GetNewEditorNode(workspace_view *View)
{
Assert(View->Type == Workspace_View_Editor);
workspace_view_editor *Editor = (workspace_view_editor *)View->Data;
workspace_editor_node *Result = 0;
if(DLLIsEmpty(Editor->FirstFreeNode))
{
Result = PushStruct(&View->Arena, workspace_editor_node);
}
else
{
Result = Editor->FirstFreeNode;
DLLRemove(Editor->FirstFreeNode, Editor->LastFreeNode, Result);
}
if(Result)
{
*Result = {};
DLLInsertLast(Editor->FirstNode, Editor->LastNode, Result);
}
return(Result);
}
//- sixten: Transformations
inline r32 Workspace_ViewToWorld(r32 Offset, r32 Scale, r32 Dim, r32 P)
{
r32 Result = (P - Dim*0.5)*(1.0/Scale) - Offset;
return(Result);
}
inline r32 Workspace_WorldToView(r32 Offset, r32 Scale, r32 Dim, r32 P)
{
r32 Result = (P + Offset)*Scale + Dim*0.5;
return(Result);
}
inline v2 Workspace_ViewToWorld(v2 Offset, r32 Scale, v2 Dim, v2 P)
{
v2 Result = (P - Dim*0.5)*(1.0/Scale) - Offset;
return(Result);
}
inline v2 Workspace_WorldToView(v2 Offset, r32 Scale, v2 Dim, v2 P)
{
v2 Result = (P + Offset)*Scale + Dim*0.5;
return(Result);
}
inline r32 Workspace_CalculateScaleFromZoomLevel(r32 ZoomLevel)
{
r32 PixelsPerUnit = 100.0;
r32 Scale = PixelsPerUnit*Pow(1.25, ZoomLevel);
return(Scale);
}
//- sixten: Commands
//- sixten: Builder code
static void Workspace_EditorDrawCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data)
{
workspace_view_editor *Editor = (workspace_view_editor *)Data;
r32 Scale = Editor->Scale;
v4 LineColor = Theme_BorderColor;
v2 Dim = DimOfRange(Box->Rect);
s32 VerticalLineCount = Dim.x / Scale + 4;
for(s32 LineIndex = -VerticalLineCount/2;
LineIndex < VerticalLineCount/2;
++LineIndex)
{
r32 OffsetX = Workspace_WorldToView(Editor->Offset.x, Scale, Dim.x, LineIndex - (s32)Editor->Offset.x);
PushQuad(Group, Box->Rect.Min + V2(OffsetX, 0), V2(1.5, Dim.y), LineColor, 0, 1.2, 0);
}
s32 HorizontalLineCount = Dim.y / Scale + 4;
for(s32 LineIndex = -HorizontalLineCount/2;
LineIndex < HorizontalLineCount/2;
++LineIndex)
{
r32 OffsetY = Workspace_WorldToView(Editor->Offset.y, Scale, Dim.y, LineIndex - (s32)Editor->Offset.y);
PushQuad(Group, Box->Rect.Min + V2(0, OffsetY), V2(Dim.x, 1.5), LineColor, 0, 1.2, 0);
}
}
static void Workspace_BuildEditor(workspace *Workspace, workspace_view *View)
{
workspace_view_editor *Editor = (workspace_view_editor *)View->Data;
// sixten(TODO): These should be able to have a strictness of 1, but they can't. Fix that.
UI_SetNextWidth(UI_Percent(1, 0));
UI_SetNextHeight(UI_Percent(1, 0));
ui_box *EditorBox = UI_MakeBoxF(UI_BoxFlag_Clip|UI_BoxFlag_Clickable, "Workspace Editor %p", View);
EditorBox->DrawCallback = Workspace_EditorDrawCallback;
EditorBox->DrawCallbackData = Editor;
r32 AnimatedZoomLevel = AnimationCurve_AnimateValueF(Editor->ZoomLevel, 0, 0.25, "Workspace Editor Zoom");
Editor->Scale = Workspace_CalculateScaleFromZoomLevel(AnimatedZoomLevel);
v2 EditorDim = DimOfRange(EditorBox->Rect);
// sixten: Build the node boxes.
for(workspace_editor_node *Node = Editor->FirstNode;
Node != 0;
Node = Node->Next)
{
v2 ViewDim = V2(2, 1.5)*Editor->Scale;
v2 ViewP = Workspace_WorldToView(Editor->Offset, Editor->Scale, EditorDim, Node->P) - ViewDim*0.5;
UI_SetNextSize(UI_Pixels(ViewDim.x, 1), UI_Pixels(ViewDim.y, 1));
UI_SetNextFixedP(ViewP);
UI_SetNextLayoutAxis(Axis2_Y);
Node->Box = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_FloatingX |
UI_BoxFlag_FloatingY |
UI_BoxFlag_DrawDropShadow,
"Workspace Editor Node %p", Node);
UI_Parent(Node->Box)
{
UI_SetNextBackgroundColor(LinearBlend(Theme_BackgroundColor, Color_Black, 0.3));
UI_SetNextSize(UI_Percent(1, 1), UI_Pixels(20, 1));
Node->TitleBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
UI_BoxFlag_DrawBorder |
UI_BoxFlag_Clickable,
"Workspace Editor Node Title");
UI_Parent(Node->TitleBox)
{
UI_Width(UI_TextContent(7, 0)) UI_Font(Font_Bold) UI_LabelF("Node");
}
}
}
// sixten: Get input from boxes.
{
workspace_editor_node *Next = 0;
for(workspace_editor_node *Node = Editor->FirstNode;
Node != 0;
Node = Next)
{
Next = Node->Next;
ui_signal Signal = UI_SignalFromBox(Node->TitleBox);
if(Signal.Dragging)
{
if(Signal.Pressed)
{
UI_StoreDragV2(Node->P);
}
v2 StartP = UI_GetDragV2();
v2 EndP = StartP + Signal.DragDelta*(1.0 / Editor->Scale);
Node->P = EndP;
}
if(Signal.Dragging || Signal.Hovering)
{
Platform.SetCursor(PlatformCursor_ArrowAll);
}
}
}
// sixten: Process the movement of the node.
{
}
// sixten: Process panning and zooming of the editor.
ui_signal Signal = UI_SignalFromBox(EditorBox);
{
if(Signal.Dragging)
{
if(Signal.Pressed)
{
UI_StoreDragV2(Editor->Offset);
}
v2 StartOffset = UI_GetDragV2();
v2 EndOffset = StartOffset + Signal.DragDelta*(1.0 / Editor->Scale);
Editor->Offset = EndOffset;
// sixten: Update node positions, as to not get a one frame delay.
for(workspace_editor_node *Node = 0;
Node != 0;
Node = Node->Next)
{
v2 ViewDim = V2(2, 1.5)*Editor->Scale;
v2 ViewP = Workspace_WorldToView(Editor->Offset, Editor->Scale, EditorDim, Node->P) - ViewDim*0.5;
Node->Box->FixedP = ViewP;
}
}
}
for(platform_event *Event = Workspace->EventList->First;
Event != 0;
Event = Event->Next)
{
if(Event->Type == PlatformEvent_MouseScroll)
{
if(Signal.Dragging)
{
UI_StoreDragV2(Editor->Offset);
UI_UpdateDragStartP();
}
Editor->ZoomLevel = Clamp(Editor->ZoomLevel + Event->Scroll.y, -4, 5);
}
}
// sixten: Process shortcuts.
if(Platform_KeyPress(Workspace->EventList, Key_Space, PlatformModifier_Ctrl))
{
Workspace_GetNewEditorNode(View);
}
}