mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
chore: restructure sound curve loader to load generic 2D graphs instead
This commit is contained in:
parent
fcb73347c2
commit
6f6a70c212
25
src/ObjCommon/Parsing/GenericGraph2D.h
Normal file
25
src/ObjCommon/Parsing/GenericGraph2D.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class GenericGraph2DKnot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
GenericGraph2DKnot() = default;
|
||||||
|
|
||||||
|
GenericGraph2DKnot(const double x, const double y)
|
||||||
|
: x(x),
|
||||||
|
y(y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GenericGraph2D
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string name;
|
||||||
|
std::vector<GenericGraph2DKnot> knots;
|
||||||
|
};
|
@ -1,214 +0,0 @@
|
|||||||
#include "SndCurveReader.h"
|
|
||||||
|
|
||||||
#include "Parsing/Impl/AbstractParser.h"
|
|
||||||
#include "Parsing/Impl/ParserSingleInputStream.h"
|
|
||||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
|
||||||
#include "Parsing/Simple/SimpleLexer.h"
|
|
||||||
#include "Parsing/Simple/SimpleParserValue.h"
|
|
||||||
|
|
||||||
enum class SndCurveParserStatus
|
|
||||||
{
|
|
||||||
EXPECT_MAGIC,
|
|
||||||
EXPECT_KNOT_COUNT,
|
|
||||||
KNOTS
|
|
||||||
};
|
|
||||||
|
|
||||||
class SndCurveParserState
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SndCurveParserStatus m_status;
|
|
||||||
size_t m_knot_count;
|
|
||||||
SndCurveReader::Result m_result;
|
|
||||||
|
|
||||||
SndCurveParserState()
|
|
||||||
: m_status(SndCurveParserStatus::EXPECT_MAGIC),
|
|
||||||
m_knot_count(0u)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using snd_sequence_t = AbstractSequence<SimpleParserValue, SndCurveParserState>;
|
|
||||||
|
|
||||||
class SndCurveMagicSequence final : public snd_sequence_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SndCurveMagicSequence()
|
|
||||||
{
|
|
||||||
const SimpleMatcherFactory create(this);
|
|
||||||
AddMatchers({
|
|
||||||
create.Keyword("SNDCURVE"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
|
||||||
{
|
|
||||||
state->m_status = SndCurveParserStatus::EXPECT_KNOT_COUNT;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SndCurveKnotCountSequence final : public snd_sequence_t
|
|
||||||
{
|
|
||||||
static constexpr auto CAPTURE_KNOT_COUNT = 1;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SndCurveKnotCountSequence()
|
|
||||||
{
|
|
||||||
const SimpleMatcherFactory create(this);
|
|
||||||
AddMatchers({
|
|
||||||
create.Integer().Capture(CAPTURE_KNOT_COUNT),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
|
||||||
{
|
|
||||||
state->m_status = SndCurveParserStatus::KNOTS;
|
|
||||||
|
|
||||||
const auto& knotCountToken = result.NextCapture(CAPTURE_KNOT_COUNT);
|
|
||||||
if (knotCountToken.IntegerValue() < 0)
|
|
||||||
throw ParsingException(knotCountToken.GetPos(), "Negative knot count is invalid");
|
|
||||||
|
|
||||||
state->m_knot_count = static_cast<size_t>(knotCountToken.IntegerValue());
|
|
||||||
state->m_result.m_knots.reserve(state->m_knot_count);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SndCurveKnotSequence final : public snd_sequence_t
|
|
||||||
{
|
|
||||||
static constexpr auto CAPTURE_X = 1;
|
|
||||||
static constexpr auto CAPTURE_Y = 2;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SndCurveKnotSequence()
|
|
||||||
{
|
|
||||||
const SimpleMatcherFactory create(this);
|
|
||||||
AddMatchers({
|
|
||||||
create
|
|
||||||
.Or({
|
|
||||||
create.FloatingPoint(),
|
|
||||||
create.Integer(),
|
|
||||||
})
|
|
||||||
.Capture(CAPTURE_X),
|
|
||||||
|
|
||||||
create
|
|
||||||
.Or({
|
|
||||||
create.FloatingPoint(),
|
|
||||||
create.Integer(),
|
|
||||||
})
|
|
||||||
.Capture(CAPTURE_Y),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static double GetValue(const SimpleParserValue& token)
|
|
||||||
{
|
|
||||||
if (token.m_type == SimpleParserValueType::INTEGER)
|
|
||||||
return static_cast<double>(token.IntegerValue());
|
|
||||||
|
|
||||||
return token.FloatingPointValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
|
||||||
{
|
|
||||||
const auto& xToken = result.NextCapture(CAPTURE_X);
|
|
||||||
const auto& yToken = result.NextCapture(CAPTURE_Y);
|
|
||||||
|
|
||||||
if (state->m_result.m_knots.size() >= state->m_knot_count)
|
|
||||||
throw ParsingException(xToken.GetPos(), "Too many knots");
|
|
||||||
|
|
||||||
const auto xValue = GetValue(xToken);
|
|
||||||
const auto yValue = GetValue(yToken);
|
|
||||||
|
|
||||||
state->m_result.m_knots.push_back(SndCurveReader::Result::Knot{xValue, yValue});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SndCurveParser final : public AbstractParser<SimpleParserValue, SndCurveParserState>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit SndCurveParser(ILexer<SimpleParserValue>* lexer)
|
|
||||||
: AbstractParser<SimpleParserValue, SndCurveParserState>(lexer, std::make_unique<SndCurveParserState>())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const std::vector<sequence_t*>& GetTestsForState() override
|
|
||||||
{
|
|
||||||
switch (m_state->m_status)
|
|
||||||
{
|
|
||||||
case SndCurveParserStatus::EXPECT_MAGIC:
|
|
||||||
{
|
|
||||||
static std::vector<sequence_t*> expectMagicSequences{
|
|
||||||
new SndCurveMagicSequence(),
|
|
||||||
};
|
|
||||||
return expectMagicSequences;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SndCurveParserStatus::EXPECT_KNOT_COUNT:
|
|
||||||
{
|
|
||||||
static std::vector<sequence_t*> expectKnotCountSequences{
|
|
||||||
new SndCurveKnotCountSequence(),
|
|
||||||
};
|
|
||||||
return expectKnotCountSequences;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SndCurveParserStatus::KNOTS:
|
|
||||||
{
|
|
||||||
static std::vector<sequence_t*> knotsSequences{
|
|
||||||
new SndCurveKnotSequence(),
|
|
||||||
};
|
|
||||||
return knotsSequences;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
throw std::runtime_error("Invalid parsing status");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
_NODISCARD SndCurveReader::Result& GetResult() const
|
|
||||||
{
|
|
||||||
return m_state->m_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
_NODISCARD bool HasExpectedKnotCount() const
|
|
||||||
{
|
|
||||||
return m_state->m_knot_count == m_state->m_result.m_knots.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SndCurveReader::SndCurveReader(std::istream& stream, const std::string& filename)
|
|
||||||
: m_stream(stream),
|
|
||||||
m_filename(filename)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<SndCurveReader::Result> SndCurveReader::Read() const
|
|
||||||
{
|
|
||||||
ParserSingleInputStream parserStream(m_stream, m_filename);
|
|
||||||
|
|
||||||
SimpleLexer::Config lexerConfig;
|
|
||||||
lexerConfig.m_emit_new_line_tokens = false;
|
|
||||||
lexerConfig.m_read_strings = false;
|
|
||||||
lexerConfig.m_read_integer_numbers = true;
|
|
||||||
lexerConfig.m_read_floating_point_numbers = true;
|
|
||||||
|
|
||||||
SimpleLexer lexer(&parserStream, std::move(lexerConfig));
|
|
||||||
SndCurveParser parser(&lexer);
|
|
||||||
|
|
||||||
if (!parser.Parse())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to parse SndCurve \"" << m_filename << "\"\n";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parser.HasExpectedKnotCount())
|
|
||||||
{
|
|
||||||
std::cerr << "Failed to load SndCurve: Actual knot count differs from expected: \"" << m_filename << "\"\n";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<Result>(std::move(parser.GetResult()));
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Utils/ClassUtils.h"
|
|
||||||
|
|
||||||
#include <istream>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class SndCurveReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Result
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct Knot
|
|
||||||
{
|
|
||||||
double m_x;
|
|
||||||
double m_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Knot> m_knots;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::istream& m_stream;
|
|
||||||
const std::string& m_filename;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SndCurveReader(std::istream& stream, const std::string& filename);
|
|
||||||
|
|
||||||
_NODISCARD std::unique_ptr<Result> Read() const;
|
|
||||||
};
|
|
@ -1,9 +1,9 @@
|
|||||||
#include "AssetLoaderSndCurve.h"
|
#include "AssetLoaderSndCurve.h"
|
||||||
|
|
||||||
#include "AssetLoading/SndCurve/SndCurveReader.h"
|
|
||||||
#include "Game/IW4/IW4.h"
|
#include "Game/IW4/IW4.h"
|
||||||
#include "ObjLoading.h"
|
#include "ObjLoading.h"
|
||||||
#include "Pool/GlobalAssetPool.h"
|
#include "Pool/GlobalAssetPool.h"
|
||||||
|
#include "Sound/SoundCurveLoader.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -11,15 +11,6 @@
|
|||||||
|
|
||||||
using namespace IW4;
|
using namespace IW4;
|
||||||
|
|
||||||
std::string AssetLoaderSndCurve::GetAssetFilename(const std::string& assetName)
|
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
|
||||||
|
|
||||||
ss << "soundaliases/" << assetName << ".vfcurve";
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* AssetLoaderSndCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
void* AssetLoaderSndCurve::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory)
|
||||||
{
|
{
|
||||||
auto* sndCurve = memory->Create<SndCurve>();
|
auto* sndCurve = memory->Create<SndCurve>();
|
||||||
@ -36,33 +27,26 @@ bool AssetLoaderSndCurve::CanLoadFromRaw() const
|
|||||||
bool AssetLoaderSndCurve::LoadFromRaw(
|
bool AssetLoaderSndCurve::LoadFromRaw(
|
||||||
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, Zone* zone) const
|
||||||
{
|
{
|
||||||
const auto filename = GetAssetFilename(assetName);
|
const auto sndCurveData = sound_curve::LoadSoundCurve(manager, assetName);
|
||||||
const auto file = searchPath->Open(filename);
|
|
||||||
if (!file.IsOpen())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const SndCurveReader reader(*file.m_stream, filename);
|
|
||||||
|
|
||||||
const auto sndCurveData = reader.Read();
|
|
||||||
|
|
||||||
if (!sndCurveData)
|
if (!sndCurveData)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sndCurveData->m_knots.size() > std::extent_v<decltype(SndCurve::knots)>)
|
if (sndCurveData->knots.size() > std::extent_v<decltype(SndCurve::knots)>)
|
||||||
{
|
{
|
||||||
std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->m_knots.size() << ")\n";
|
std::cerr << "Failed to load SndCurve \"" << assetName << "\": Too many knots (" << sndCurveData->knots.size() << ")\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* sndCurve = memory->Create<SndCurve>();
|
auto* sndCurve = memory->Create<SndCurve>();
|
||||||
sndCurve->filename = memory->Dup(assetName.c_str());
|
sndCurve->filename = memory->Dup(assetName.c_str());
|
||||||
sndCurve->knotCount = static_cast<uint16_t>(sndCurveData->m_knots.size());
|
sndCurve->knotCount = static_cast<uint16_t>(sndCurveData->knots.size());
|
||||||
|
|
||||||
for (auto i = 0u; i < std::extent_v<decltype(SndCurve::knots)>; i++)
|
for (auto i = 0u; i < std::extent_v<decltype(SndCurve::knots)>; i++)
|
||||||
{
|
{
|
||||||
if (i < sndCurveData->m_knots.size())
|
if (i < sndCurveData->knots.size())
|
||||||
{
|
{
|
||||||
const auto& [x, y] = sndCurveData->m_knots[i];
|
const auto& [x, y] = sndCurveData->knots[i];
|
||||||
sndCurve->knots[i][0] = static_cast<float>(x);
|
sndCurve->knots[i][0] = static_cast<float>(x);
|
||||||
sndCurve->knots[i][1] = static_cast<float>(y);
|
sndCurve->knots[i][1] = static_cast<float>(y);
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
class AssetLoaderSndCurve final : public BasicAssetLoader<ASSET_TYPE_SOUND_CURVE, SndCurve>
|
class AssetLoaderSndCurve final : public BasicAssetLoader<ASSET_TYPE_SOUND_CURVE, SndCurve>
|
||||||
{
|
{
|
||||||
static std::string GetAssetFilename(const std::string& assetName);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
_NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override;
|
||||||
_NODISCARD bool CanLoadFromRaw() const override;
|
_NODISCARD bool CanLoadFromRaw() const override;
|
||||||
|
229
src/ObjLoading/Parsing/Graph2D/Graph2DReader.cpp
Normal file
229
src/ObjLoading/Parsing/Graph2D/Graph2DReader.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include "Graph2DReader.h"
|
||||||
|
|
||||||
|
#include "Parsing/Impl/AbstractParser.h"
|
||||||
|
#include "Parsing/Impl/ParserSingleInputStream.h"
|
||||||
|
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||||
|
#include "Parsing/Simple/SimpleLexer.h"
|
||||||
|
#include "Parsing/Simple/SimpleParserValue.h"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
|
||||||
|
namespace graph2d
|
||||||
|
{
|
||||||
|
enum class SndCurveParserStatus
|
||||||
|
{
|
||||||
|
EXPECT_MAGIC,
|
||||||
|
EXPECT_KNOT_COUNT,
|
||||||
|
KNOTS
|
||||||
|
};
|
||||||
|
|
||||||
|
class SndCurveParserState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SndCurveParserStatus m_status;
|
||||||
|
size_t m_expected_knot_count;
|
||||||
|
GenericGraph2D m_result;
|
||||||
|
|
||||||
|
SndCurveParserState()
|
||||||
|
: m_status(SndCurveParserStatus::EXPECT_MAGIC),
|
||||||
|
m_expected_knot_count(0u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using snd_sequence_t = AbstractSequence<SimpleParserValue, SndCurveParserState>;
|
||||||
|
|
||||||
|
class SndCurveMagicSequence final : public snd_sequence_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SndCurveMagicSequence(std::string magicWord)
|
||||||
|
{
|
||||||
|
const SimpleMatcherFactory create(this);
|
||||||
|
AddMatchers({
|
||||||
|
create.Keyword(std::move(magicWord)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
|
{
|
||||||
|
state->m_status = SndCurveParserStatus::EXPECT_KNOT_COUNT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SndCurveKnotCountSequence final : public snd_sequence_t
|
||||||
|
{
|
||||||
|
static constexpr auto CAPTURE_KNOT_COUNT = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SndCurveKnotCountSequence()
|
||||||
|
{
|
||||||
|
const SimpleMatcherFactory create(this);
|
||||||
|
AddMatchers({
|
||||||
|
create.Integer().Capture(CAPTURE_KNOT_COUNT),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
|
{
|
||||||
|
state->m_status = SndCurveParserStatus::KNOTS;
|
||||||
|
|
||||||
|
const auto& knotCountToken = result.NextCapture(CAPTURE_KNOT_COUNT);
|
||||||
|
if (knotCountToken.IntegerValue() < 0)
|
||||||
|
throw ParsingException(knotCountToken.GetPos(), "Negative knot count is invalid");
|
||||||
|
|
||||||
|
state->m_expected_knot_count = static_cast<size_t>(knotCountToken.IntegerValue());
|
||||||
|
state->m_result.knots.reserve(state->m_expected_knot_count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SndCurveKnotSequence final : public snd_sequence_t
|
||||||
|
{
|
||||||
|
static constexpr auto CAPTURE_X = 1;
|
||||||
|
static constexpr auto CAPTURE_Y = 2;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SndCurveKnotSequence()
|
||||||
|
{
|
||||||
|
const SimpleMatcherFactory create(this);
|
||||||
|
AddMatchers({
|
||||||
|
create
|
||||||
|
.Or({
|
||||||
|
create.FloatingPoint(),
|
||||||
|
create.Integer(),
|
||||||
|
})
|
||||||
|
.Capture(CAPTURE_X),
|
||||||
|
|
||||||
|
create
|
||||||
|
.Or({
|
||||||
|
create.FloatingPoint(),
|
||||||
|
create.Integer(),
|
||||||
|
})
|
||||||
|
.Capture(CAPTURE_Y),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static double GetValue(const SimpleParserValue& token)
|
||||||
|
{
|
||||||
|
if (token.m_type == SimpleParserValueType::INTEGER)
|
||||||
|
return token.IntegerValue();
|
||||||
|
|
||||||
|
return token.FloatingPointValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ProcessMatch(SndCurveParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
|
{
|
||||||
|
const auto& xToken = result.NextCapture(CAPTURE_X);
|
||||||
|
const auto& yToken = result.NextCapture(CAPTURE_Y);
|
||||||
|
|
||||||
|
if (state->m_result.knots.size() >= state->m_expected_knot_count)
|
||||||
|
throw ParsingException(xToken.GetPos(), std::format("More knots than expected ({})", state->m_expected_knot_count));
|
||||||
|
|
||||||
|
const auto xValue = GetValue(xToken);
|
||||||
|
const auto yValue = GetValue(yToken);
|
||||||
|
|
||||||
|
state->m_result.knots.emplace_back(xValue, yValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SndCurveParser final : public AbstractParser<SimpleParserValue, SndCurveParserState>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SndCurveParser(ILexer<SimpleParserValue>* lexer, std::string magicWord)
|
||||||
|
: AbstractParser(lexer, std::make_unique<SndCurveParserState>()),
|
||||||
|
m_magic_sequence(std::move(magicWord)),
|
||||||
|
m_magic_sequences({&m_magic_sequence})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const std::vector<sequence_t*>& GetTestsForState() override
|
||||||
|
{
|
||||||
|
switch (m_state->m_status)
|
||||||
|
{
|
||||||
|
case SndCurveParserStatus::EXPECT_MAGIC:
|
||||||
|
return m_magic_sequences;
|
||||||
|
|
||||||
|
case SndCurveParserStatus::EXPECT_KNOT_COUNT:
|
||||||
|
{
|
||||||
|
static std::vector<sequence_t*> expectKnotCountSequences{
|
||||||
|
new SndCurveKnotCountSequence(),
|
||||||
|
};
|
||||||
|
return expectKnotCountSequences;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SndCurveParserStatus::KNOTS:
|
||||||
|
{
|
||||||
|
static std::vector<sequence_t*> knotsSequences{
|
||||||
|
new SndCurveKnotSequence(),
|
||||||
|
};
|
||||||
|
return knotsSequences;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
throw std::runtime_error("Invalid parsing status");
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
_NODISCARD GenericGraph2D& GetResult() const
|
||||||
|
{
|
||||||
|
return m_state->m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
_NODISCARD bool HasExpectedKnotCount() const
|
||||||
|
{
|
||||||
|
return GetExpectedKnotCount() == GetActualKnotCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t GetExpectedKnotCount() const
|
||||||
|
{
|
||||||
|
return m_state->m_expected_knot_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] size_t GetActualKnotCount() const
|
||||||
|
{
|
||||||
|
return m_state->m_result.knots.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SndCurveMagicSequence m_magic_sequence;
|
||||||
|
std::vector<sequence_t*> m_magic_sequences;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<GenericGraph2D>
|
||||||
|
Read(const std::string& graphTypeName, std::string graphMagicWord, std::istream& stream, const std::string& fileName, std::string graphName)
|
||||||
|
{
|
||||||
|
ParserSingleInputStream parserStream(stream, fileName);
|
||||||
|
|
||||||
|
SimpleLexer::Config lexerConfig;
|
||||||
|
lexerConfig.m_emit_new_line_tokens = false;
|
||||||
|
lexerConfig.m_read_strings = false;
|
||||||
|
lexerConfig.m_read_integer_numbers = true;
|
||||||
|
lexerConfig.m_read_floating_point_numbers = true;
|
||||||
|
|
||||||
|
SimpleLexer lexer(&parserStream, std::move(lexerConfig));
|
||||||
|
SndCurveParser parser(&lexer, std::move(graphMagicWord));
|
||||||
|
|
||||||
|
if (!parser.Parse())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Failed to parse {} \"{}\"\n", graphTypeName, graphName);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parser.HasExpectedKnotCount())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Failed to load {} \"{}\": Actual knot count ({}) differs from expected ({})\n",
|
||||||
|
graphTypeName,
|
||||||
|
graphName,
|
||||||
|
parser.GetActualKnotCount(),
|
||||||
|
parser.GetExpectedKnotCount());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_unique<GenericGraph2D>(std::move(parser.GetResult()));
|
||||||
|
}
|
||||||
|
} // namespace graph2d
|
12
src/ObjLoading/Parsing/Graph2D/Graph2DReader.h
Normal file
12
src/ObjLoading/Parsing/Graph2D/Graph2DReader.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Parsing/GenericGraph2D.h"
|
||||||
|
|
||||||
|
#include <istream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace graph2d
|
||||||
|
{
|
||||||
|
[[nodiscard]] std::unique_ptr<GenericGraph2D>
|
||||||
|
Read(const std::string& graphTypeName, std::string graphMagicWord, std::istream& stream, const std::string& fileName, std::string graphName);
|
||||||
|
}
|
23
src/ObjLoading/Sound/SoundCurveLoader.cpp
Normal file
23
src/ObjLoading/Sound/SoundCurveLoader.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "SoundCurveLoader.h"
|
||||||
|
|
||||||
|
#include "Parsing/Graph2D/Graph2DReader.h"
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace sound_curve
|
||||||
|
{
|
||||||
|
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName)
|
||||||
|
{
|
||||||
|
auto* searchPath = manager->GetAssetLoadingContext()->m_raw_search_path;
|
||||||
|
const auto fileName = std::format("soundaliases/{}.vfcurve", soundCurveName);
|
||||||
|
const auto file = searchPath->Open(fileName);
|
||||||
|
if (!file.IsOpen())
|
||||||
|
{
|
||||||
|
std::cerr << std::format("Failed to open file for sound curve \"{}\"\n", soundCurveName);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return graph2d::Read("sound curve", "SNDCURVE", *file.m_stream, fileName, soundCurveName);
|
||||||
|
}
|
||||||
|
} // namespace sound_curve
|
11
src/ObjLoading/Sound/SoundCurveLoader.h
Normal file
11
src/ObjLoading/Sound/SoundCurveLoader.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AssetLoading/IAssetLoadingManager.h"
|
||||||
|
#include "Parsing/GenericGraph2D.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace sound_curve
|
||||||
|
{
|
||||||
|
std::unique_ptr<GenericGraph2D> LoadSoundCurve(const IAssetLoadingManager* manager, const std::string& soundCurveName);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user