Structuring SDL Programs

Controlling Drawing Order for Overlapping UI Components in SDL

How is the drawing order determined if components overlap in this UI structure?

Abstract art representing computer programming

The drawing order, which determines which components appear "on top" when they overlap, is determined by the sequence of rendering calls. SDL (like many 2D graphics systems) uses the Painter's Algorithm: elements drawn later are painted over elements drawn earlier.

Order in Manager Loops

In our UI class example that uses a std::vector to hold components:

// UI.h (Simplified Vector Example)
class UI {
  // ...
  void Render(SDL_Surface* Surface) const {
    for (auto& Component : Components) {
      Component->Render(Surface); // Render in vector order
    }
  }
private:
  std::vector<std::unique_ptr<Component>> Components;
};

The components are rendered in the order they appear in the Components vector.

  • Components[0] is drawn first.
  • Components[1] is drawn next, potentially overlapping Components[0].
  • The last element in the vector is drawn last and will appear on top of all others if overlaps occur.

Order in Hierarchical Managers

In the hierarchical example:

// UI.h (Hierarchical Example)
class UI {
  // ...
  void Render(SDL_Surface* Surface) const {
    TopMenu.Render(Surface);    // Drawn first (bottom layer)
    Rectangles.Render(Surface); // Drawn second (middle layer)
    BottomMenu.Render(Surface); // Drawn third (top layer)
  }
private:
  Header TopMenu;
  Grid Rectangles;
  Footer BottomMenu;
};

The order is explicitly defined by the sequence of calls within UI::Render:

  1. TopMenu is rendered first.
  2. Rectangles (the grid) is rendered next. If any part of the grid overlaps the TopMenu, the grid will appear on top in that area.
  3. BottomMenu is rendered last. If it overlaps either the TopMenu or the Rectangles, the BottomMenu will appear on top.

Controlling the Drawing Order

You can control the visual layering by changing the order of rendering operations:

Reorder Calls in Managers: In the hierarchical example, if you wanted the TopMenu to appear above everything else, you would simply call TopMenu.Render(Surface) last within UI::Render.

Reorder Vector Elements: In the vector-based example, changing the order of elements within the std::vector will change the drawing order. This is less common for static UI layouts but might be used for dynamically changing layers (e.g., bringing a selected window to the front).

Techniques like std::swap or rearranging the vector before rendering could achieve this.

// Conceptual: Bring last element to front visually
// (Not efficient for frequent changes)
if (Components.size() > 1) {
  // Find the element to bring to front
  // For simplicity, let's say it's the last one
  auto ElementToBringForward = std::move(Components.back());
  Components.pop_back();
  // Insert it at the desired position (e.g., end again)
  // Wait, if last is already on top, this logic is flawed.
  // More likely: move a specific element TO the end.

  // Example: Move element at index 'idx' to the end
  size_t idx = /* index of element to bring to top */;
  if (idx < Components.size() - 1) {
     auto it = Components.begin() + idx;
     std::rotate(it, it + 1, Components.end());
  }
}

// Now render in the (potentially) new order
for (auto& Component : Components) {
  Component->Render(Surface);
}

Implement Z-Ordering: For more complex layering needs, you might introduce a concept of Z-order (depth). Each component could have a Z value. Before rendering, you would sort the components based on their Z value and then render them in that sorted order. This provides more explicit control over layering than just sequential ordering.

// Conceptual: Using Z-order
class Component {
public:
  virtual void Render(SDL_Surface* s) const = 0;
  virtual int GetZOrder() const { return 0; } // Default Z
  // ...
};

// In UI::Render
// 1. Sort components by Z-order
std::stable_sort(Components.begin(), Components.end(),
  [](const auto& a, const auto& b) {
    return a->GetZOrder() < b->GetZOrder();
  }
);

// 2. Render in sorted order
for (auto& Comp : Components) {
  Comp->Render(Surface);
}

For most simple UIs based on the lesson structure, controlling the order of calls within the Render functions of your manager classes is sufficient.

This Question is from the Lesson:

Structuring SDL Programs

Discover how to organize SDL components using manager classes, inheritance, and polymorphism for cleaner code.

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Structuring SDL Programs

Discover how to organize SDL components using manager classes, inheritance, and polymorphism for cleaner code.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

This course includes:

  • 110 Lessons
  • 92% Positive Reviews
  • Regularly Updated
  • Help and FAQs
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved