Skip to content

Commit

Permalink
Add DynamicArray class and use it in PlayedSounds class
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkrupinski committed Oct 30, 2023
1 parent bef804a commit e56210a
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 9 deletions.
17 changes: 8 additions & 9 deletions Source/FeatureHelpers/PlayedSounds.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
#include <MemoryPatterns/FileSystemPatterns.h>
#include <MemoryPatterns/SoundSystemPatterns.h>
#include "PlayedSound.h"
#include <Utils/DynamicArray.h>

class PlayedSounds {
public:
void removeExpiredSounds(float curtime, float lifetime) noexcept
{
for (std::size_t i = 0; i < numberOfSounds;) {
for (std::size_t i = 0; i < sounds.getSize();) {
auto& sound = sounds[i];
if (!sound.isAlive(curtime, lifetime))
removeSound(sound);
Expand Down Expand Up @@ -53,29 +54,27 @@ class PlayedSounds {
if (!predicate(std::string_view{buffer.data()}))
continue;

if (std::ranges::find(sounds.begin(), sounds.begin() + numberOfSounds, channel.guid, &PlayedSound::guid) != sounds.begin() + numberOfSounds)
if (std::ranges::find(sounds, channel.guid, &PlayedSound::guid) != sounds.end())
continue;

if (numberOfSounds < sounds.size())
sounds[numberOfSounds++] = PlayedSound{ .guid = channel.guid, .spawnTime = curtime, .origin = channelInfo2.memory[i].origin };
sounds.pushBack(PlayedSound{ .guid = channel.guid, .spawnTime = curtime, .origin = channelInfo2.memory[i].origin });
}
}

template <typename F>
void forEach(F&& f) const noexcept
{
std::for_each_n(sounds.cbegin(), numberOfSounds, std::forward<F>(f));
std::ranges::for_each(sounds, std::forward<F>(f));
}

private:
void removeSound(PlayedSound& sound) noexcept
{
sound = sounds[numberOfSounds - 1];
--numberOfSounds;
sound = sounds.back();
sounds.popBack();
}

cs2::SoundChannels** soundChannels{ SoundSystemPatterns::soundChannels() };
cs2::CBaseFileSystem** fileSystem{ FileSystemPatterns::fileSystem() };
std::array<PlayedSound, 100> sounds; // TODO: dynamically allocate
std::size_t numberOfSounds{0};
DynamicArray<PlayedSound> sounds;
};
1 change: 1 addition & 0 deletions Source/Osiris.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
<ClInclude Include="UI\Panorama\SetCommandHandler.h" />
<ClInclude Include="Utils\Align.h" />
<ClInclude Include="Utils\CharUtils.h" />
<ClInclude Include="Utils\DynamicArray.h" />
<ClInclude Include="Utils\FieldOffset.h" />
<ClInclude Include="Utils\FlagsBuilder.h" />
<ClInclude Include="Utils\GenericFunctionPointer.h" />
Expand Down
3 changes: 3 additions & 0 deletions Source/Osiris.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,9 @@
<ClInclude Include="FeatureHelpers\GlobalVarsProvider.h">
<Filter>FeatureHelpers</Filter>
</ClInclude>
<ClInclude Include="Utils\DynamicArray.h">
<Filter>Utils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="UI\Panorama\CreateGUI.js">
Expand Down
126 changes: 126 additions & 0 deletions Source/Utils/DynamicArray.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#pragma once

#include <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <type_traits>

#include <MemoryAllocation/MemoryAllocator.h>
#include <MemoryAllocation/MemoryDeleter.h>
#include <MemoryAllocation/UniquePtr.h>

template <typename T>
requires std::is_trivially_copyable_v<T>
class DynamicArray {
public:
DynamicArray() = default;
DynamicArray(DynamicArray&&) = delete;
DynamicArray(const DynamicArray&) = delete;
DynamicArray& operator=(DynamicArray&&) = delete;
DynamicArray& operator=(const DynamicArray&) = delete;

[[nodiscard]] T* begin() noexcept
{
return memory.get();
}

[[nodiscard]] T* end() noexcept
{
return memory.get() + size;
}

[[nodiscard]] const T* begin() const noexcept
{
return memory.get();
}

[[nodiscard]] const T* end() const noexcept
{
return memory.get() + size;
}

[[nodiscard]] std::size_t getCapacity() const noexcept
{
return memory.get_deleter().getNumberOfElements();
}

[[nodiscard]] std::size_t getSize() const noexcept
{
return size;
}

[[nodiscard]] T& operator[](std::size_t index) noexcept
{
assert(index < size);
return memory.get()[index];
}

bool pushBack(const T& value) noexcept
{
if (ensureCapacityForNewElement()) [[likely]] {
new (memory.get() + size) T{ value };
++size;
return true;
}
return false;
}

[[nodiscard]] T& back() noexcept
{
assert(size > 0);
return memory.get()[size - 1];
}

void popBack() noexcept
{
assert(size > 0);
std::destroy_at(&back());
--size;
}

private:
[[nodiscard]] static std::size_t calculateNewCapacity(std::size_t currentCapacity) noexcept
{
return currentCapacity + currentCapacity / 2 + 1;
}

[[nodiscard]] std::size_t calculateNewCapacity() const noexcept
{
return calculateNewCapacity(getCapacity());
}

[[nodiscard]] bool ensureCapacityForNewElement() noexcept
{
return size < getCapacity() || growMemory(calculateNewCapacity());
}

[[nodiscard]] bool growMemory(std::size_t newCapacity) noexcept
{
assert(newCapacity > getCapacity());
if (const auto newMemory = createNewMemory(newCapacity)) {
memory.reset(newMemory);
memory.get_deleter() = MemoryDeleter<T[]>(newCapacity);
return true;
}
return false;
}

[[nodiscard]] T* createNewMemory(std::size_t newCapacity) const noexcept
{
if (const auto newMemory = MemoryAllocator<T[]>::allocate(newCapacity)) {
copyMemoryTo(newMemory);
return reinterpret_cast<T*>(newMemory);
}
return nullptr;
}

void copyMemoryTo(std::byte* newMemory) const noexcept
{
if (size > 0)
std::memcpy(newMemory, memory.get(), size * sizeof(T));
}

UniquePtr<T[]> memory;
std::size_t size{0};
};

0 comments on commit e56210a

Please sign in to comment.