UI_CUSTOM_DRAW_CALLBACK(BuildNavViewDrawCallback) { scene_view *SceneView = (scene_view *)Data; SV_DrawBackground(SceneView, Box, Group); } static scene_nav_item_node *W_SceneNavItemNodeAlloc(arena *Arena, workspace_view_nav_editor *Editor) { scene_nav_item_node *Result = Editor->FirstFree; if(Result) { DLLRemove(Editor->FirstFree, Editor->LastFree, Result); *Result = {}; } else { Result = PushStruct(Arena, scene_nav_item_node); } DLLInsertLast(Editor->Items.First, Editor->Items.Last, Result); Editor->Items.Count += 1; return(Result); } static void W_SceneNavItemNodeRelease(workspace_view_nav_editor *Editor, scene_nav_item_node *Node) { DLLInsertLast(Editor->FirstFree, Editor->LastFree, Node); Editor->Items.Count -= 1; } static void W_SetupNavEditor(workspace_view *View, string FileContents) { //- sixten(TODO): deserialize data } static void W_BuildNavEditor(workspace_view *View) { workspace_view_nav_editor *Editor = (workspace_view_nav_editor *)View->Data; scene_view *SceneView = SV_GetState(); UI_BackgroundColor(V4(0.25, 0.25, 0.25, 1)) UI_BorderColor(V4(0.45, 0.45, 0.45, 1)) UI_WidthFill UI_Height(UI_Em(2.0f, 1.0f)) UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawBorder, "Workspace Nav Editor Toolbar")) { UI_Width(UI_TextContent(10, 1.0f)) UI_Font(Font_Icons) if(UI_ButtonF("%U", FontIcon_UserPlus).Clicked) { scene_nav_item_node *NewNode = W_SceneNavItemNodeAlloc(View->Arena, Editor); NewNode->Item = G_DefaultSceneNavItem; } } UI_Row() { //- sixten: build inspector panel UI_Width(UI_Percent(0.2f, 1.0f)) UI_HeightFill UI_Parent(UI_MakeBox(UI_BoxFlag_DrawBorder, StrLit("Workspace Nav Editor Inspector"))) { scene_nav_item_node *SelectedItem = Editor->SelectedItem; if(SelectedItem) { } else UI_WidthFill { UI_LabelF("No item selected."); } } //- sixten: build nav view UI_Row() { //- sixten: calculate nav view size r32 VerticalPad = 0; r32 HorizontalPad = 0; { ui_box *ParentBox = UI_TopParent(); v2_r32 ParentDim = DimOfRange(ParentBox->Rect); r32 WidthOverHeight = ParentDim.x / ParentDim.y; r32 TargetRatio = 16.0f / 9.0f; if(WidthOverHeight > TargetRatio) { VerticalPad = ParentDim.x - ParentDim.y*TargetRatio; } else { HorizontalPad = ParentDim.y - ParentDim.x/TargetRatio; } } //- sixten: do the building of the nav view UI_Padding(UI_Pixels(VerticalPad/2, 1)) { UI_Column() UI_Padding(UI_Pixels(HorizontalPad/2, 1)) { UI_SetNextWidth(UI_Percent(1, 0)); UI_SetNextHeight(UI_Percent(1, 0)); UI_SetNextLayoutAxis(Axis2_Y); ui_box *Box = UI_MakeBox(UI_BoxFlag_Clip, StrLit("Nav View")); UI_EquipBoxCustomDrawCallback(Box, BuildNavViewDrawCallback, SceneView); v2_r32 BoxDim = UI_CalculateBoxDim(Box); r32 GlobalScale = CalculateGlobalScaleFromDim(BoxDim); //- sixten: build all nav items s32 ItemIndex = 0; for(scene_nav_item_node *Node = Editor->Items.First; Node != 0; Node = Node->Next, ItemIndex += 1) { scene_nav_item *Item = &Node->Item; //- sixten: calculate item position r32 AppliedScale = GlobalScale*Item->Scale; render_handle Texture = TextureFromAssetID(Item->TextureID); v2_r32 TextureDim = ConvertV2ToR32(DimFromTexture(Texture)); v2_r32 TextureOrigin = Hadamard(TextureDim, Item->Origin); v2_r32 Dim = TextureDim*AppliedScale; v2_r32 OriginP = TextureOrigin*AppliedScale; //- sixten: build the item scene_nav_item_info *Data = PushStruct(UI_FrameArena(), scene_nav_item_info); Data->Item = Item; UI_SetNextHoverCursor(PlatformCursor_Hand); UI_SetNextSize(UI_Pixels(Dim.x, 1), UI_Pixels(Dim.y, 1)); ui_box *ItemBox = UI_MakeBoxF(UI_BoxFlag_Clickable|UI_BoxFlag_FloatingX|UI_BoxFlag_FloatingY, "View Item Box %i", ItemIndex); UI_EquipBoxCustomDrawCallback(ItemBox, BuildNavItemDrawCallback, Data); //- sixten: handle signals { ui_signal Signal = UI_SignalFromBox(ItemBox); Data->Signal = Signal; //- sixten: inspect pressed item if(Signal.Pressed) { Editor->SelectedItem = Node; } //- sixten: handle dragging if(Signal.Dragging) { if(Signal.Pressed) { UI_StoreDragV2(Item->P); } Item->P = UI_GetDragV2() + Signal.DragDelta/BoxDim*2; } } //- sixten: apply the calculated position v2_r32 OffsetP = BoxDim*(V2R32(1, 1) + Item->P)*0.5f; ItemBox->FixedP = (OffsetP-OriginP); } } } } } }