/** \brief Draw a target circle and threshold along with the current pad position. \param idX the ID of the horizontal axis \param idY the ID of the vertical axis \param axesValues the axes raw values \param threshRadius the radius of the filtering threshold \ingroup ControllerTest */ void drawPadTarget(const int idX, const int idY, const std::vector<float> & axesValues, const float threshRadius){ const ImU32 whiteColor = IM_COL32(255,255,255, 255); const int aidRX = idX; const int aidRY = idY; const float magRX = aidRX >= 0 ? axesValues[aidRX] : 0.0f; const float magRY = aidRY >= 0 ? axesValues[aidRY] : 0.0f; // Detect overflow on each axis. const bool overflow = (std::abs(magRX) > 1.0) || (std::abs(magRY) > 1.0); // Get current rendering position on screen. const ImVec2 posR = ImGui::GetCursorScreenPos(); ImDrawList * drawListR = ImGui::GetWindowDrawList(); // Draw "safe" region. drawListR->AddRectFilled(posR, ImVec2(posR.x + 200, posR.y + 200), overflow ? IM_COL32(30,0,0,255) : IM_COL32(0,30,0, 255)); drawListR->AddCircleFilled(ImVec2(posR.x + 100, posR.y + 100), threshRadius, IM_COL32(0, 0, 0, 255), 32); // Draw frame and cross lines. drawListR->AddRect(posR, ImVec2(posR.x + 200, posR.y + 200), overflow ? IM_COL32(255,0,0, 255) : whiteColor); drawListR->AddLine(ImVec2(posR.x + 100, posR.y), ImVec2(posR.x + 100, posR.y+200), whiteColor); drawListR->AddLine(ImVec2(posR.x, posR.y + 100), ImVec2(posR.x + 200, posR.y+100), whiteColor); // Draw threshold and unit radius circles. drawListR->AddCircle(ImVec2(posR.x + 100, posR.y + 100), threshRadius, IM_COL32(0, 255, 0, 255), 32); drawListR->AddCircle(ImVec2(posR.x + 100, posR.y + 100), 100, whiteColor, 32); // Current axis position. drawListR->AddCircleFilled(ImVec2(posR.x + magRX * 100 + 100, posR.y + magRY * 100 + 100), 10, whiteColor); }
/** \brief Draw a target line and threshold along with the current trigger position. \param idT the ID of the trigger axis \param axesValues the axes raw values \param threshRadius the value of the filtering threshold \ingroup ControllerTest */ void drawTriggerTarget(const int idT, const std::vector<float> & axesValues, const float threshRadius){ const ImU32 whiteColor = IM_COL32(255,255,255, 255); const int aidLT = idT; const float magLT = aidLT >= 0 ? axesValues[aidLT]*0.5+0.5f : 0.0f; // Detect overflow. const bool overflow = (magLT > 1.0f || magLT < 0.0f); // Get current rendering position on screen. const ImVec2 posR = ImGui::GetCursorScreenPos(); ImDrawList * drawListR = ImGui::GetWindowDrawList(); const float thresholdY = (200.0f-2.0f*threshRadius); const float currentY = 200*(1.0f-magLT); // Draw "safe" region. drawListR->AddRectFilled(posR, ImVec2(posR.x+40, posR.y+thresholdY), overflow ? IM_COL32(30,0,0,255) : IM_COL32(0,30,0, 255)); // Draw threshold line. drawListR->AddLine(ImVec2(posR.x, posR.y + thresholdY), ImVec2(posR.x + 40, posR.y+thresholdY), IM_COL32(0, 255, 0, 255)); // Draw frame. drawListR->AddRect(posR, ImVec2(posR.x + 40, posR.y + 200), overflow ? IM_COL32(255,0,0, 255) : whiteColor); // Current axis position. drawListR->AddLine(ImVec2(posR.x, posR.y + currentY), ImVec2(posR.x + 40, posR.y + currentY), whiteColor, 4.0f); }
static void fillRectangle(Scintilla::PRectangle _rc, Scintilla::ColourDesired _color) { const uint32_t abgr = (uint32_t)_color.AsLong(); ImVec2 pos = ImGui::GetCursorScreenPos(); ImDrawList* drawList = ImGui::GetWindowDrawList(); drawList->AddDrawCmd(); drawList->AddRectFilled( ImVec2(_rc.left + pos.x, _rc.top + pos.y) , ImVec2(_rc.right + pos.x, _rc.bottom + pos.y) , abgr ); }
void TransferFunctionUi::drawThresholdControl() { // draw threshold indicator const ImVec2 p = ui::GetCursorScreenPos(); ImDrawList* drawList = ui::GetWindowDrawList(); auto width = ui::GetContentRegionAvailWidth(); ImU32 gray = ImColor(0.5f, 0.5f, 0.5f, 0.5f); float x = p.x; float y = p.y - 35.0f - 4.0f; float steps = width / 255; ImGuiStyle& style = ui::GetStyle(); auto threshold = getThreshold(); if (threshold.x > 0) { drawList->AddRectFilled(ImVec2(x, y - 120), ImVec2(x + threshold.x * steps, y), gray, style.FrameRounding); } if (threshold.y < 255) { drawList->AddRectFilled(ImVec2(x + threshold.y * steps, y - 120), ImVec2(x + 255 * steps, y), gray, style.FrameRounding); } // draw threshold controls ui::BeginGroup(); ui::PushItemWidth(-2.0f); if (ui::SliderInt2("##Threshold", value_ptr(threshold), 0, 255)) { setThreshold(threshold.x, threshold.y); updateFunction(); } ui::PopItemWidth(); ui::EndGroup(); }
/* pOptionalHoveredIndex: a ptr to an optional int that is set to -1 if no tab label is hovered by the mouse. * pOptionalItemOrdering: an optional static array of unique integers from 0 to numTabs-1 that maps the tab label order. If one of the numbers is replaced by -1 the tab label is not visible (closed). It can be read/modified at runtime. * allowTabReorder (requires pOptionalItemOrdering): allows tab reordering through drag and drop (it modifies pOptionalItemOrdering). * allowTabClosingThroughMMB (requires pOptionalItemOrdering): closes the tabs when MMB is clicked on them, by setting the tab value in pOptionalItemOrdering to -1. * pOptionalClosedTabIndex (requires allowTabClosingThroughMMB): out variable (int pointer) that returns the index of the closed tab in last call or -1. * pOptionalClosedTabIndexInsideItemOrdering: same as above, but index of the pOptionalItemOrdering array. */ IMGUI_API bool TabLabels(int numTabs, const char** tabLabels, int& selectedIndex, ImVec2 btnSize, const char** tabLabelTooltips, bool wrapMode, int *pOptionalHoveredIndex, int* pOptionalItemOrdering, bool allowTabReorder, bool allowTabClosingThroughMMB, int *pOptionalClosedTabIndex, int *pOptionalClosedTabIndexInsideItemOrdering) { ImGuiStyle& style = ImGui::GetStyle(); const ImVec2 itemSpacing = style.ItemSpacing; const ImVec4 color = style.Colors[ImGuiCol_Button]; const ImVec4 colorActive = style.Colors[ImGuiCol_ButtonActive]; const ImVec4 colorHover = style.Colors[ImGuiCol_ButtonHovered]; const ImVec4 colorText = style.Colors[ImGuiCol_Text]; style.ItemSpacing.x = 10; style.ItemSpacing.y = 10; style.FrameRounding = 2.0; const ImVec4 colorSelectedTab(color.x,color.y,color.z,color.w*0.5f); const ImVec4 colorSelectedTabHovered(colorHover.x,colorHover.y,colorHover.z,colorHover.w*0.5f); const ImVec4 colorSelectedTabText(colorText.x*0.8f,colorText.y*0.8f,colorText.z*0.6f,colorText.w*0.8f); //ImGui::ClampColor(colorSelectedTabText); if (numTabs>0 && (selectedIndex<0 || selectedIndex>=numTabs)) { if (!pOptionalItemOrdering) selectedIndex = 0; else selectedIndex = -1; } if (pOptionalHoveredIndex) *pOptionalHoveredIndex = -1; if (pOptionalClosedTabIndex) *pOptionalClosedTabIndex = -1; if (pOptionalClosedTabIndexInsideItemOrdering) *pOptionalClosedTabIndexInsideItemOrdering = -1; float windowWidth = 0.f,sumX=0.f; if (wrapMode) windowWidth = ImGui::GetWindowWidth() - style.WindowPadding.x - (ImGui::GetScrollMaxY()>0 ? style.ScrollbarSize : 0.f); static int draggingTabIndex = -1;int draggingTabTargetIndex = -1; // These are indices inside pOptionalItemOrdering static ImVec2 draggingTabSize(0,0); static ImVec2 draggingTabOffset(0,0); const bool isMMBreleased = ImGui::IsMouseReleased(2); const bool isMouseDragging = ImGui::IsMouseDragging(0,2.f); int justClosedTabIndex = -1,newSelectedIndex = selectedIndex; bool selection_changed = false;bool noButtonDrawn = true; for (int j = 0,i; j < numTabs; j++) { i = pOptionalItemOrdering ? pOptionalItemOrdering[j] : j; if (i==-1) continue; if (!wrapMode) {if (!noButtonDrawn) ImGui::SameLine();} else if (sumX > 0.f) { sumX+=style.ItemSpacing.x; // Maybe we can skip it if we use SameLine(0,0) below sumX+=ImGui::CalcTextSize(tabLabels[i]).x+2.f*style.FramePadding.x; if (sumX>windowWidth) sumX = 0.f; else ImGui::SameLine(); } if (i == selectedIndex) { // Push the style style.Colors[ImGuiCol_Button] = colorSelectedTab; style.Colors[ImGuiCol_ButtonActive] = colorSelectedTab; style.Colors[ImGuiCol_ButtonHovered] = colorSelectedTabHovered; style.Colors[ImGuiCol_Text] = colorSelectedTabText; } // Draw the button ImGui::PushID(i); // otherwise two tabs with the same name would clash. if (ImGui::Button(tabLabels[i], btnSize)) {selection_changed = (selectedIndex!=i);newSelectedIndex = i;} ImGui::PopID(); if (i == selectedIndex) { // Reset the style style.Colors[ImGuiCol_Button] = color; style.Colors[ImGuiCol_ButtonActive] = colorActive; style.Colors[ImGuiCol_ButtonHovered] = colorHover; style.Colors[ImGuiCol_Text] = colorText; } noButtonDrawn = false; if (wrapMode) { if (sumX==0.f) sumX = style.WindowPadding.x + ImGui::GetItemRectSize().x; // First element of a line } else if (isMouseDragging && allowTabReorder && pOptionalItemOrdering) { // We still need sumX if (sumX==0.f) sumX = style.WindowPadding.x + ImGui::GetItemRectSize().x; // First element of a line else sumX+=style.ItemSpacing.x + ImGui::GetItemRectSize().x; } if (ImGui::IsItemHoveredRect()) { if (pOptionalHoveredIndex) *pOptionalHoveredIndex = i; if (tabLabelTooltips && tabLabelTooltips[i] && strlen(tabLabelTooltips[i])>0) ImGui::SetTooltip("%s",tabLabelTooltips[i]); if (pOptionalItemOrdering) { if (allowTabReorder) { if (isMouseDragging) { if (draggingTabIndex==-1) { draggingTabIndex = j; draggingTabSize = ImGui::GetItemRectSize(); const ImVec2& mp = ImGui::GetIO().MousePos; const ImVec2 draggingTabCursorPos = ImGui::GetCursorPos(); draggingTabOffset=ImVec2( mp.x+draggingTabSize.x*0.5f-sumX+ImGui::GetScrollX(), mp.y+draggingTabSize.y*0.5f-draggingTabCursorPos.y+ImGui::GetScrollY() ); } } else if (draggingTabIndex>=0 && draggingTabIndex<numTabs && draggingTabIndex!=j){ draggingTabTargetIndex = j; // For some odd reasons this seems to get called only when draggingTabIndex < i ! (Probably during mouse dragging ImGui owns the mouse someway and sometimes ImGui::IsItemHovered() is not getting called) } } if (allowTabClosingThroughMMB) { if (isMMBreleased) { justClosedTabIndex = i; if (pOptionalClosedTabIndex) *pOptionalClosedTabIndex = i; if (pOptionalClosedTabIndexInsideItemOrdering) *pOptionalClosedTabIndexInsideItemOrdering = j; pOptionalItemOrdering[j] = -1; } } } } } selectedIndex = newSelectedIndex; // Draw tab label while mouse drags it if (draggingTabIndex>=0 && draggingTabIndex<numTabs) { const ImVec2& mp = ImGui::GetIO().MousePos; const ImVec2 wp = ImGui::GetWindowPos(); ImVec2 start(wp.x+mp.x-draggingTabOffset.x-draggingTabSize.x*0.5f,wp.y+mp.y-draggingTabOffset.y-draggingTabSize.y*0.5f); const ImVec2 end(start.x+draggingTabSize.x,start.y+draggingTabSize.y); ImDrawList* drawList = ImGui::GetWindowDrawList(); const float draggedBtnAlpha = 0.65f; const ImVec4& btnColor = style.Colors[ImGuiCol_Button]; drawList->AddRectFilled(start,end,ImColor(btnColor.x,btnColor.y,btnColor.z,btnColor.w*draggedBtnAlpha),style.FrameRounding); start.x+=style.FramePadding.x;start.y+=style.FramePadding.y; const ImVec4& txtColor = style.Colors[ImGuiCol_Text]; drawList->AddText(start,ImColor(txtColor.x,txtColor.y,txtColor.z,txtColor.w*draggedBtnAlpha),tabLabels[pOptionalItemOrdering[draggingTabIndex]]); ImGui::SetMouseCursor(ImGuiMouseCursor_Move); } // Drop tab label if (draggingTabTargetIndex!=-1) { // swap draggingTabIndex and draggingTabTargetIndex in pOptionalItemOrdering const int tmp = pOptionalItemOrdering[draggingTabTargetIndex]; pOptionalItemOrdering[draggingTabTargetIndex] = pOptionalItemOrdering[draggingTabIndex]; pOptionalItemOrdering[draggingTabIndex] = tmp; //fprintf(stderr,"%d %d\n",draggingTabIndex,draggingTabTargetIndex); // draggingTabTargetIndex = draggingTabIndex = -1; } // Reset draggingTabIndex if necessary if (!isMouseDragging) draggingTabIndex = -1; // Change selected tab when user closes the selected tab if (selectedIndex == justClosedTabIndex && selectedIndex>=0) { selectedIndex = -1; for (int j = 0,i; j < numTabs; j++) { i = pOptionalItemOrdering ? pOptionalItemOrdering[j] : j; if (i==-1) continue; selectedIndex = i; break; } } // Restore the style style.Colors[ImGuiCol_Button] = color; style.Colors[ImGuiCol_ButtonActive] = colorActive; style.Colors[ImGuiCol_ButtonHovered] = colorHover; style.Colors[ImGuiCol_Text] = colorText; style.ItemSpacing = itemSpacing; return selection_changed; }
PreviewTab::PreviewTab(Context* context) : Tab(context) { SetID("d75264a1-4179-4350-8e9f-ec4e4a15a7fa"); SetTitle("Game"); isUtility_ = true; windowFlags_ = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; view_ = context_->CreateObject<Texture2D>(); // Ensure parts of texture are not left dirty when viewport does not cover entire texture. SubscribeToEvent(E_CAMERAVIEWPORTRESIZED, [this](StringHash, VariantMap& args) { Clear(); }); // Ensure views are updated upon component addition or removal. SubscribeToEvent(E_COMPONENTADDED, [this](StringHash, VariantMap& args) { OnComponentUpdated(static_cast<Component*>(args[ComponentAdded::P_COMPONENT].GetPtr())); }); SubscribeToEvent(E_COMPONENTREMOVED, [this](StringHash, VariantMap& args) { OnComponentUpdated(static_cast<Component*>(args[ComponentRemoved::P_COMPONENT].GetPtr())); }); // Reload viewports when renderpath or postprocess was modified. SubscribeToEvent(E_RELOADFINISHED, [this](StringHash, VariantMap& args) { using namespace ReloadFinished; Scene* scene = GetSubsystem<SceneManager>()->GetActiveScene(); if (scene == nullptr) return; if (auto* resource = GetEventSender()->Cast<Resource>()) { if (resource->GetName().starts_with("RenderPaths/") || resource->GetName().starts_with("PostProcess/")) { if (auto* manager = scene->GetOrCreateComponent<SceneMetadata>()) { auto& viewportComponents = manager->GetCameraViewportComponents(); for (auto& component : viewportComponents) component->RebuildRenderPath(); Clear(); } } } }); // On plugin code reload all scene state is serialized, plugin library is reloaded and scene state is unserialized. // This way scene recreates all plugin-provided components on reload and gets to use new versions of them. SubscribeToEvent(E_EDITORUSERCODERELOADSTART, [&](StringHash, VariantMap&) { SceneTab* tab = GetSubsystem<Editor>()->GetTab<SceneTab>(); if (tab == nullptr || tab->GetScene() == nullptr) return; tab->GetUndo().SetTrackingEnabled(false); tab->SaveState(sceneReloadState_); tab->GetScene()->RemoveAllChildren(); tab->GetScene()->RemoveAllComponents(); }); SubscribeToEvent(E_EDITORUSERCODERELOADEND, [&](StringHash, VariantMap&) { SceneTab* tab = GetSubsystem<Editor>()->GetTab<SceneTab>(); if (tab == nullptr || tab->GetScene() == nullptr) return; tab->RestoreState(sceneReloadState_); tab->GetUndo().SetTrackingEnabled(true); }); SubscribeToEvent(E_ENDALLVIEWSRENDER, [this](StringHash, VariantMap&) { RenderUI(); }); SubscribeToEvent(E_SCENEACTIVATED, [this](StringHash, VariantMap&) { UpdateViewports(); }); SubscribeToEvent(E_ENDRENDERINGSYSTEMUI, [this](StringHash, VariantMap&) { if (simulationStatus_ == SCENE_SIMULATION_STOPPED) dim_ = Max(dim_ - GetTime()->GetTimeStep() * 10, 0.f); else dim_ = Min(dim_ + GetTime()->GetTimeStep() * 6, 1.f); if (dim_ > M_EPSILON) { // Dim other windows except for preview. ImGuiContext& g = *ui::GetCurrentContext(); const ea::string& sceneTabName = GetSubsystem<Editor>()->GetTab<SceneTab>()->GetUniqueTitle(); for (int i = 0; i < g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; if (window->ParentWindow != nullptr && window->DockNode != nullptr) { // Ignore any non-leaf windows if (window->DockNode->ChildNodes[0] || window->DockNode->ChildNodes[1]) continue; if (!window->DockTabIsVisible) continue; // Editor scene viewport is not dimmed. if (strcmp(window->Name, sceneTabName.c_str()) == 0) continue; // Game preview viewport is not dimmed. if (strcmp(window->Name, GetUniqueTitle().c_str()) == 0) continue; ImDrawList* drawLists = ui::GetBackgroundDrawList(window->Viewport); const ImU32 color = ui::GetColorU32(ImGuiCol_ModalWindowDimBg, dim_); drawLists->AddRectFilled(window->Pos, window->Pos + window->Size, color); } } } }); }