private void UpdateCamera() { var mouseInfo = ImGuiHelper.CreateMouseState(); if (ImGui.IsAnyMouseDown() && !_mouseDown) { OnMouseDown(mouseInfo); _mouseDown = true; } if (ImGui.IsMouseReleased(ImGuiMouseButton.Left) || ImGui.IsMouseReleased(ImGuiMouseButton.Right) || ImGui.IsMouseReleased(ImGuiMouseButton.Middle)) { OnMouseUp(mouseInfo); _mouseDown = false; } if (_mouseDown) { OnMouseMove(mouseInfo); } OnMouseWheel(mouseInfo); }
private void LoadProperties(NodeBase node, bool onLoad) { if (node.Tag is IPropertyUI) { //A UI type that can display rendered IMGUI code. var propertyUI = (IPropertyUI)node.Tag; if (ActiveEditor == null || ActiveEditor.GetType() != propertyUI.GetTypeUI()) { var instance = Activator.CreateInstance(propertyUI.GetTypeUI()); ActiveEditor = instance; } if (onLoad) { propertyUI.OnLoadUI(ActiveEditor); } propertyUI.OnRenderUI(ActiveEditor); } else if (node.Tag is STGenericTexture) { //A generic image viewer for image types. ImageEditor.LoadEditor((STGenericTexture)node.Tag); } //A basic UI type to generate properties like a property grid. else if (node.Tag is IPropertyDisplay) { var prop = ((IPropertyDisplay)node.Tag); if (prop.PropertyDisplay != null) { ImGuiHelper.LoadProperties(prop.PropertyDisplay); } } }
private void OnEnter() { var mouseInfo = ImGuiHelper.CreateMouseState(); originMouse = new System.Drawing.Point(mouseInfo.X, mouseInfo.Y); mouseWheelPrevious = mouseInfo.WheelPrecise; }
private void UpdateCurveEvents() { var mouseInfo = ImGuiHelper.CreateMouseState(); bool controlDown = ImGui.GetIO().KeyCtrl; bool shiftDown = ImGui.GetIO().KeyShift; if (onEnter) { CurveEditor.ResetMouse(mouseInfo); onEnter = false; } if (ImGui.IsAnyMouseDown() && !_mouseDown) { CurveEditor.OnMouseDown(mouseInfo); previousMouseWheel = 0; _mouseDown = true; } if (ImGui.IsMouseReleased(ImGuiMouseButton.Left) || ImGui.IsMouseReleased(ImGuiMouseButton.Right) || ImGui.IsMouseReleased(ImGuiMouseButton.Middle)) { CurveEditor.OnMouseUp(mouseInfo); _mouseDown = false; } if (previousMouseWheel == 0) { previousMouseWheel = mouseInfo.WheelPrecise; } mouseInfo.Delta = mouseInfo.WheelPrecise - previousMouseWheel; previousMouseWheel = mouseInfo.WheelPrecise; // if (_mouseDown) CurveEditor.OnMouseMove(mouseInfo); CurveEditor.OnMouseWheel(mouseInfo, controlDown, shiftDown); }
public void DrawNode(NodeBase node, float itemHeight) { bool HasText = node.Header != null && node.Header.IndexOf(_searchText, StringComparison.OrdinalIgnoreCase) >= 0; char icon = IconManager.FOLDER_ICON; if (node.Children.Count == 0) { icon = IconManager.FILE_ICON; } if (node.Tag is STGenericMesh) { icon = IconManager.MESH_ICON; } if (node.Tag is STGenericModel) { icon = IconManager.MODEL_ICON; } ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags.None; flags |= ImGuiTreeNodeFlags.SpanFullWidth; if (node.Children.Count == 0 || isSearch) { flags |= ImGuiTreeNodeFlags.Leaf; } else { flags |= ImGuiTreeNodeFlags.OpenOnDoubleClick; flags |= ImGuiTreeNodeFlags.OpenOnArrow; } if (node.IsExpanded && !isSearch) { flags |= ImGuiTreeNodeFlags.DefaultOpen; } //Node was selected manually outside the outliner so update the list if (node.IsSelected && !SelectedNodes.Contains(node)) { SelectedNodes.Add(node); } //Node was deselected manually outside the outliner so update the list if (!node.IsSelected && SelectedNodes.Contains(node)) { SelectedNodes.Remove(node); } if (SelectedNodes.Contains(node)) { flags |= ImGuiTreeNodeFlags.Selected; } if (isSearch && HasText || !isSearch) { //Add active file format styling. This determines what file to save. //For files inside archives, it gets the parent of the file format to save. bool isActiveFile = false; isActiveFile = ActiveFileFormat == node.Tag; bool isRenaming = node == renameNode && isNameEditing && node.Tag is IRenamableNode; //Improve tree node spacing. var spacing = ImGui.GetStyle().ItemSpacing; ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(spacing.X, 1)); //Make the active file noticable if (isActiveFile) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.834f, 0.941f, 1.000f, 1.000f)); } //Align the text to improve selection sizing. ImGui.AlignTextToFramePadding(); //Disable selection view in renaming handler to make text more clear if (isRenaming) { flags &= ~ImGuiTreeNodeFlags.Selected; flags &= ~ImGuiTreeNodeFlags.SpanFullWidth; } //Load the expander or selection if (isSearch) { ImGui.Selectable(node.ID, flags.HasFlag(ImGuiTreeNodeFlags.Selected)); } else { node.IsExpanded = ImGui.TreeNodeEx(node.ID, flags, $""); } ImGui.SameLine(); ImGuiHelper.IncrementCursorPosX(3); bool leftClicked = ImGui.IsItemClicked(ImGuiMouseButton.Left); bool rightClicked = ImGui.IsItemClicked(ImGuiMouseButton.Right); bool nodeFocused = ImGui.IsItemFocused(); bool isToggleOpened = ImGui.IsItemToggledOpen(); bool beginDragDropSource = !isRenaming && node.Tag is IDragDropNode && ImGui.BeginDragDropSource(); if (beginDragDropSource) { //Placeholder pointer data. Instead use drag/drop nodes from GetDragDropNode() GCHandle handle1 = GCHandle.Alloc(node.ID); ImGui.SetDragDropPayload("OUTLINER_ITEM", (IntPtr)handle1, sizeof(int), ImGuiCond.Once); handle1.Free(); dragDroppedNode = node; //Display icon for texture types if (node.Tag is STGenericTexture) { LoadTextureIcon(node); } //Display text for item being dragged ImGui.Button($"{node.Header}"); ImGui.EndDragDropSource(); } bool hasContextMenu = node is IContextMenu || node is IExportReplaceNode || node.Tag is ICheckableNode || node.Tag is IContextMenu || node.Tag is IExportReplaceNode || node.Tag is STGenericTexture; //Apply a pop up menu for context items. Only do this if the menu has possible items used if (hasContextMenu && SelectedNodes.Contains(node)) { ImGui.PushID(node.Header); if (ImGui.BeginPopupContextItem("##OUTLINER_POPUP", ImGuiPopupFlags.MouseButtonRight)) { SetupRightClickMenu(node); ImGui.EndPopup(); } ImGui.PopID(); } if (node.HasCheckBox) { ImGui.SetItemAllowOverlap(); ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(2, 2)); bool check = node.IsChecked; if (ImGui.Checkbox($"##check{node.ID}", ref check)) { foreach (var n in SelectedNodes) { n.IsChecked = check; } } ImGui.PopStyleVar(); ImGui.SameLine(); ImGuiHelper.IncrementCursorPosX(3); } //Load the icon if (node.Tag is STGenericTexture) { LoadTextureIcon(node); } else { IconManager.DrawIcon(icon); ImGui.SameLine(); ImGuiHelper.IncrementCursorPosX(3); } ImGui.AlignTextToFramePadding(); //if (node.Tag is ICheckableNode) // ImGuiHelper.IncrementCursorPosY(-2); if (!isRenaming) { ImGui.Text(node.Header); } else { var renamable = node.Tag as IRenamableNode; var bg = ImGui.GetStyle().Colors[(int)ImGuiCol.WindowBg]; //Make the textbox frame background blend with the tree background //This is so we don't see the highlight color and can see text clearly ImGui.PushStyleColor(ImGuiCol.FrameBg, bg); ImGui.PushStyleColor(ImGuiCol.Border, new Vector4(1, 1, 1, 1)); ImGui.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1); var length = ImGui.CalcTextSize(renameText).X + 20; ImGui.PushItemWidth(length); if (ImGui.InputText("##RENAME_NODE", ref renameText, 512, ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CallbackCompletion | ImGuiInputTextFlags.CallbackHistory | ImGuiInputTextFlags.NoHorizontalScroll)) { renamable.Renamed(renameText); node.Header = renameText; isNameEditing = false; } if (!ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Left)) { isNameEditing = false; } ImGui.PopItemWidth(); ImGui.PopStyleVar(); ImGui.PopStyleColor(2); } ImGui.PopStyleVar(); if (isActiveFile) { ImGui.PopStyleColor(); } if (!isRenaming) { //Check for rename selection on selected renamable node if (node.IsSelected && node.Tag is IRenamableNode && RENAME_ENABLE) { bool renameStarting = renameClickTime != 0; bool wasCancelled = false; //Mouse click before editing started cancels the event if (renameStarting && leftClicked) { renameClickTime = 0; renameStarting = false; wasCancelled = true; } //Check for delay if (renameStarting) { //Create a delay between actions. This can be cancelled out during a mouse click var diff = ImGui.GetTime() - renameClickTime; if (diff > RENAME_DELAY_TIME) { //Name edit executed. Setup data for renaming. isNameEditing = true; renameNode = node; renameText = ((IRenamableNode)node.Tag).GetRenameText(); //Reset the time renameClickTime = 0; } } //User has started a rename click. Start a time check if (leftClicked && renameClickTime == 0 && !wasCancelled) { //Do a small delay for the rename event renameClickTime = ImGui.GetTime(); } } //Click event executed on item if ((leftClicked || rightClicked) && !isToggleOpened) //Prevent selection change on toggle { //Reset all selection unless shift/control held down if (!ImGui.GetIO().KeyCtrl&& !ImGui.GetIO().KeyShift) { foreach (var n in SelectedNodes) { n.IsSelected = false; } SelectedNodes.Clear(); } //Check selection range if (ImGui.GetIO().KeyShift) { SelectedRangeIndex = node.DisplayIndex; SelectRange = true; } else { SelectedIndex = node.DisplayIndex; } //Add the clicked node to selection. SelectedNodes.Add(node); node.IsSelected = true; } else if (nodeFocused && !isToggleOpened && !node.IsSelected) { if (!ImGui.GetIO().KeyCtrl&& !ImGui.GetIO().KeyShift) { foreach (var n in SelectedNodes) { n.IsSelected = false; } SelectedNodes.Clear(); } //Add the clicked node to selection. SelectedNodes.Add(node); node.IsSelected = true; } if (leftClicked && node.IsSelected) { if (node is ArchiveHiearchy && node.Tag == null) { var archiveWrapper = (ArchiveHiearchy)node; archiveWrapper.OpenFileFormat(); archiveWrapper.IsExpanded = true; } } //Update the active file format when selected. (updates dockspace layout and file menus) if (node.Tag is IFileFormat && node.IsSelected) { if (ActiveFileFormat != node.Tag) { ActiveFileFormat = (IFileFormat)node.Tag; } } else if (node.IsSelected && node.Parent != null) { } } } if (isSearch || node.IsExpanded) { //Todo find a better alternative to clip parents //Clip only the last level if (ClipNodes && node.Children.Count > 0 && node.Children[0].Children.Count == 0) { var children = node.Children.ToList(); if (isSearch) { children = GetSearchableNodes(children); } var clipper = new ImGuiListClipper2(children.Count, itemHeight); clipper.ItemsCount = children.Count; for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd; line_i++) // display only visible items { DrawNode(children[line_i], itemHeight); } } else { foreach (var child in node.Children) { DrawNode(child, itemHeight); } } if (!isSearch) { ImGui.TreePop(); } } }
public void ShowMenus() { if (ImGui.BeginMenu("Save Settings")) { var comp = ActiveFileFormat.FileInfo.Compression; var label = comp == null ? "None" : comp.ToString(); if (ImGui.BeginCombo("Compression", label)) { if (ImGui.Selectable("None", comp == null)) { ActiveFileFormat.FileInfo.Compression = null; } foreach (var format in FileManager.GetCompressionFormats()) { bool isSelected = format == ActiveFileFormat.FileInfo.Compression; if (ImGui.Selectable(format.ToString(), isSelected)) { ActiveFileFormat.FileInfo.Compression = format; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } if (comp != null) { ImGui.Checkbox($"Compress with {comp}?", ref saveCompression); ImGui.InputInt("Compression Level", ref yazoCompressionLevel, 1, 1); } ImGui.EndMenu(); } if (ImGui.BeginMenu("Debug")) { debugWindow = true; ImGui.EndMenu(); } if (ImGui.BeginMenu("Lighting Editor")) { showLightingEditor = true; ImGui.EndMenu(); } if (debugWindow) { if (ImGui.Begin("Pipeline View")) { var size = ImGui.GetWindowSize(); var tex = Viewport.Pipeline._context.ColorPicker.GetDebugPickingDisplay(); if (tex != null) { ImGuiHelper.DisplayFramebufferImage(tex.ID, size); } ImGui.End(); } } }
public void Render() { //Menu if (ImGui.BeginMenuBar()) { if (ImGui.BeginMenu("View Setting")) { if (ImGui.BeginMenu("Background")) { ImGui.Checkbox("Display", ref DrawableBackground.Display); ImGui.ColorEdit3("Color Top", ref DrawableBackground.BackgroundTop); ImGui.ColorEdit3("Color Bottom", ref DrawableBackground.BackgroundBottom); ImGui.EndMenu(); } if (ImGui.BeginMenu("Grid")) { ImGui.Checkbox("Display", ref DrawableFloor.Display); ImGui.ColorEdit4("Grid Color", ref DrawableFloor.GridColor); ImGui.InputInt("Grid Cell Count", ref Toolbox.Core.Runtime.GridSettings.CellAmount); ImGui.InputFloat("Grid Cell Size", ref Toolbox.Core.Runtime.GridSettings.CellSize); ImGui.EndMenu(); } // ImGui.Checkbox("VSync", ref Toolbox.Core.Runtime.EnableVSync); ImGui.Checkbox("Wireframe", ref Toolbox.Core.Runtime.RenderSettings.Wireframe); ImGui.Checkbox("WireframeOverlay", ref Toolbox.Core.Runtime.RenderSettings.WireframeOverlay); ImGui.EndMenu(); } if (ImGui.BeginMenu($"Shading [{Runtime.DebugRendering}]")) { foreach (var mode in Enum.GetValues(typeof(Runtime.DebugRender))) { bool isSelected = (Runtime.DebugRender)mode == Runtime.DebugRendering; if (ImGui.Selectable(mode.ToString(), isSelected)) { Runtime.DebugRendering = (Runtime.DebugRender)mode; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndMenu(); } if (ImGui.BeginMenu("Camera")) { if (ImGui.Button("Reset Transform")) { Pipeline._context.Camera.TargetPosition = new OpenTK.Vector3(0, 1, -5); Pipeline._context.Camera.RotationX = 0; Pipeline._context.Camera.RotationY = 0; Pipeline._context.Camera.UpdateMatrices(); } ImGuiHelper.InputFromBoolean("Orthographic", Pipeline._context.Camera, "IsOrthographic"); ImGuiHelper.InputFromFloat("Fov (Degrees)", Pipeline._context.Camera, "FovDegrees", true, 1f); if (Pipeline._context.Camera.FovDegrees != 45) { ImGui.SameLine(); if (ImGui.Button("Reset")) { Pipeline._context.Camera.FovDegrees = 45; } } ImGuiHelper.InputFromFloat("ZFar", Pipeline._context.Camera, "ZFar", true, 1f); if (Pipeline._context.Camera.ZFar != 100000.0f) { ImGui.SameLine(); if (ImGui.Button("Reset")) { Pipeline._context.Camera.ZFar = 100000.0f; } } ImGuiHelper.InputFromFloat("ZNear", Pipeline._context.Camera, "ZNear", true, 0.1f); if (Pipeline._context.Camera.ZNear != 0.1f) { ImGui.SameLine(); if (ImGui.Button("Reset")) { Pipeline._context.Camera.ZNear = 0.1f; } } ImGuiHelper.InputFromFloat("Zoom Speed", Pipeline._context.Camera, "ZoomSpeed", true, 0.1f); if (Pipeline._context.Camera.ZoomSpeed != 1.0f) { ImGui.SameLine(); if (ImGui.Button("Reset")) { Pipeline._context.Camera.ZoomSpeed = 1.0f; } } ImGuiHelper.InputFromFloat("Pan Speed", Pipeline._context.Camera, "PanSpeed", true, 0.1f); if (Pipeline._context.Camera.PanSpeed != 1.0f) { ImGui.SameLine(); if (ImGui.Button("Reset")) { Pipeline._context.Camera.PanSpeed = 1.0f; } } ImGui.EndMenu(); } if (ImGui.BeginMenu("Reset Animations")) { parentWindow.Reset(); ImGui.EndMenu(); } ImGui.EndMenuBar(); var menuBG = ImGui.GetStyle().Colors[(int)ImGuiCol.MenuBarBg]; ImGui.PushStyleColor(ImGuiCol.WindowBg, menuBG); ImGui.PushStyleColor(ImGuiCol.ChildBg, menuBG); if (ImGui.BeginChild("viewport_menu2", new System.Numerics.Vector2(350, 22))) { ImGui.AlignTextToFramePadding(); ImGui.Text("Active Model(s)"); ImGui.SameLine(); if (ImGui.BeginCombo("##model_select", selectedModel)) { bool isSelected = "All Models" == selectedModel; if (ImGui.Selectable("All Models", isSelected)) { selectedModel = "All Models"; } if (isSelected) { ImGui.SetItemDefaultFocus(); } foreach (var file in Pipeline.Files) { string name = file.Renderer.Name; isSelected = name == selectedModel; if (ImGui.Selectable(name, isSelected)) { selectedModel = name; } if (isSelected) { ImGui.SetItemDefaultFocus(); } } ImGui.EndCombo(); } } ImGui.EndChild(); ImGui.PopStyleColor(2); } //Make sure the entire viewport is within a child window to have accurate mouse and window sizing relative to the space it uses. if (ImGui.BeginChild("viewport_child1")) { var size = ImGui.GetWindowSize(); if (Pipeline.Width != (int)size.X || Pipeline.Height != (int)size.Y) { Pipeline.Width = (int)size.X; Pipeline.Height = (int)size.Y; Pipeline.OnResize(); } Pipeline.RenderScene(); if (ImGui.IsWindowFocused() && ImGui.IsWindowHovered() || ForceUpdate || _mouseDown) { ForceUpdate = false; if (!onEnter) { Pipeline.ResetPrevious(); onEnter = true; } //Only update scene when necessary UpdateCamera(); } else { onEnter = false; //Reset drag/dropped model data if mouse leaves the viewport during a drag event if (DragDroppedModel != null) { DragDroppedModel.DragDroppedOnLeave(); DragDroppedModel = null; } } var id = Pipeline.GetViewportTexture(); ImGui.Image((IntPtr)id, size, new System.Numerics.Vector2(0, 1), new System.Numerics.Vector2(1, 0)); if (ImGui.BeginDragDropTarget()) { ImGuiPayloadPtr outlinerDrop = ImGui.AcceptDragDropPayload("OUTLINER_ITEM", ImGuiDragDropFlags.AcceptNoDrawDefaultRect | ImGuiDragDropFlags.AcceptBeforeDelivery); if (outlinerDrop.IsValid()) { //Drag/drop things onto meshes var mouseInfo = CreateMouseState(); var picked = Pipeline.GetPickedObject(mouseInfo); //Picking object changed. if (DragDroppedModel != picked) { //Set exit drop event for previous model if (DragDroppedModel != null) { DragDroppedModel.DragDroppedOnLeave(); } DragDroppedModel = picked; //Model has changed so call the enter event if (picked != null) { picked.DragDroppedOnEnter(); } } if (picked != null) { //Set the drag/drop event var node = Outliner.GetDragDropNode(); picked.DragDropped(node.Tag); } } ImGui.EndDragDropTarget(); } } ImGui.EndChild(); }
public void Render(STGenericTexture texture) { if (ImageCanvas == null) { Init(); } var size = ImGui.GetWindowSize(); ActiveTexture = texture; var menuSize = new Vector2(22, 22); var propertyWindowSize = new Vector2(size.X, size.Y / 2 - 20); var canvasWindowSize = new Vector2(size.X, size.Y / 2 - 20); if (ImGui.BeginChild("##IMAGE_TABMENU", propertyWindowSize, true)) { ImGui.BeginTabBar("image_menu"); if (ImguiCustomWidgets.BeginTab("image_menu", "Properties")) { ImGuiHelper.LoadProperties(ActiveTexture.DisplayProperties, ActiveTexture.DisplayPropertiesChanged); ImGui.EndTabItem(); } if (ImguiCustomWidgets.BeginTab("image_menu", "Channels")) { ImGui.EndTabItem(); } if (ImguiCustomWidgets.BeginTab("image_menu", "User Data")) { ImGui.EndTabItem(); } ImGui.EndTabBar(); } ImGui.EndChild(); if (ImGui.BeginChild("CANVAS_WINDOW", canvasWindowSize, false, ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.MenuBar)) { if (ImGui.BeginMenuBar()) { if (ImGui.BeginMenu("File")) { ImGui.EndMenu(); } if (ImGui.BeginMenu("Edit")) { ImGui.EndMenu(); } if (ImGui.BeginMenu("View")) { ImGui.EndMenu(); } if (ImGui.BeginMenu("Image")) { ImGui.EndMenu(); } if (ImGui.BeginMenu("Adjustments")) { ImGui.EndMenu(); } ImGui.PushItemWidth(150); if (ImGui.BeginCombo("##imageCB", selectedBackground)) { if (ImGui.Selectable("Checkerboard")) { selectedBackground = "Checkerboard"; } ; if (ImGui.Selectable("Black")) { selectedBackground = "Black"; } ; if (ImGui.Selectable("White")) { selectedBackground = "White"; } ; if (ImGui.Selectable("Custom")) { selectedBackground = "White"; } ; ImGui.EndMenu(); } ImGui.PopItemWidth(); ImGui.EndMenuBar(); } //Make icon buttons invisible aside from the icon itself. ImGui.PushStyleColor(ImGuiCol.Button, new Vector4()); { //Draw icon bar ImGui.ImageButton((IntPtr)IconManager.GetTextureIcon("SAVE_BUTTON"), menuSize); ImGui.SameLine(); ImGui.ImageButton((IntPtr)IconManager.GetTextureIcon("IMG_EDIT_BUTTON"), menuSize); ImGui.SameLine(); ImguiCustomWidgets.ImageButtonToggle( IconManager.GetTextureIcon("IMG_ALPHA_BUTTON"), IconManager.GetTextureIcon("IMG_NOALPHA_BUTTON"), ref DisplayAlpha, menuSize); } ImGui.PopStyleColor(); //Draw the array and mip level counter buttons ImGui.AlignTextToFramePadding(); ImGui.Text("Array Level " + $"{currentArrayLevel} / {texture.ArrayCount - 1}"); ImGui.SameLine(); if (ImGui.Button("<", menuSize)) { AdjustArrayLevel(-1); } ImGui.SameLine(); if (ImGui.Button(">", menuSize)) { AdjustArrayLevel(1); } ImGui.SameLine(); ImGui.Text("Mip Level " + $"{currentMipLevel} / {texture.MipCount - 1}"); ImGui.SameLine(); if (ImGui.Button("<", menuSize)) { AdjustMipLevel(-1); } ImGui.SameLine(); if (ImGui.Button(">", menuSize)) { AdjustMipLevel(1); } //Draw the main image canvas DrawImageCanvas(canvasWindowSize); } ImGui.EndChild(); /* if (ImGui.BeginMenuBar()) * { * * }*/ }