| 289 | /// <returns>The node that contains inserted an item or null if failed to find a free space.</returns> |
| 290 | template<class... Args> |
| 291 | NodeType* Insert(SizeType itemWidth, SizeType itemHeight, SizeType itemPadding, Args&&... args) |
| 292 | { |
| 293 | NodeType* result; |
| 294 | const SizeType paddedWidth = itemWidth + itemPadding; |
| 295 | const SizeType paddedHeight = itemHeight + itemPadding; |
| 296 | |
| 297 | // Check if we're free and just the right size |
| 298 | if (!IsUsed && Width == paddedWidth && Height == paddedHeight) |
| 299 | { |
| 300 | // Insert into this slot |
| 301 | IsUsed = true; |
| 302 | result = (NodeType*)this; |
| 303 | result->OnInsert(Forward<Args>(args)...); |
| 304 | return result; |
| 305 | } |
| 306 | |
| 307 | // If there are left and right slots there are empty regions around this slot (it also means this slot is occupied) |
| 308 | if (Left || Right) |
| 309 | { |
| 310 | if (Left) |
| 311 | { |
| 312 | result = Left->Insert(itemWidth, itemHeight, itemPadding, Forward<Args>(args)...); |
| 313 | if (result) |
| 314 | return result; |
| 315 | } |
| 316 | if (Right) |
| 317 | { |
| 318 | result = Right->Insert(itemWidth, itemHeight, itemPadding, Forward<Args>(args)...); |
| 319 | if (result) |
| 320 | return result; |
| 321 | } |
| 322 | } |
| 323 | |
| 324 | // This slot can't fit or has been already occupied |
| 325 | if (IsUsed || paddedWidth > Width || paddedHeight > Height) |
| 326 | { |
| 327 | // Not enough space |
| 328 | return nullptr; |
| 329 | } |
| 330 | |
| 331 | // The width and height of the new child node |
| 332 | const SizeType remainingWidth = Width - paddedWidth; |
| 333 | const SizeType remainingHeight = Height - paddedHeight; |
| 334 | |
| 335 | // Split the remaining area around this slot into two children |
| 336 | if (remainingHeight <= remainingWidth) |
| 337 | { |
| 338 | // Split vertically |
| 339 | Left = New<NodeType>(X, Y + paddedHeight, paddedWidth, remainingHeight); |
| 340 | Right = New<NodeType>(X + paddedWidth, Y, remainingWidth, Height); |
| 341 | } |
| 342 | else |
| 343 | { |
| 344 | // Split horizontally |
| 345 | Left = New<NodeType>(X + paddedWidth, Y, remainingWidth, paddedHeight); |
| 346 | Right = New<NodeType>(X, Y + paddedHeight, Width, remainingHeight); |
| 347 | } |
| 348 | |