Skip to content

Commit 8dbcdde

Browse files
authored
Merge development work
- documented basic things that are included in the engine for assisted development - added tests for Array, String and fixed various bugs - added tests for PPMem - completely replaced FFMpeg with WebM playback (AV1 / Opus) - rewritten EgfMan into sysLib and ImGui, dropping wxWidgets version of the tool - fixed Github CI issues and made tests runnable - various bug fixes
2 parents 8bec90c + 834ca8c commit 8dbcdde

108 files changed

Lines changed: 19507 additions & 6894 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/linux_build.yml‎

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,23 @@ on:
2828

2929
env:
3030
PROJECT_NAME: auto_tests
31-
BUILD_CONFIGURATION: Release
3231
BUILD_PLATFORM: x64
32+
TESTS: ds_tests ppmem_tests scripting_tests
3333

3434
EXE_SUFFIX:
35-
BUILD_CONFIGURATION_LOWER: retail
3635

3736

3837
jobs:
3938
build:
4039
runs-on: ubuntu-latest
40+
strategy:
41+
fail-fast: false
42+
matrix:
43+
include:
44+
- configuration: Debug
45+
make_config: debug
46+
- configuration: Release
47+
make_config: release
4148

4249
steps:
4350
- uses: actions/checkout@v3
@@ -62,6 +69,16 @@ jobs:
6269
run: ./utils/premake5 --file=premake5-tests.lua gmake2
6370

6471
- name: make
65-
working-directory: ./build
66-
run: make config=${{env.BUILD_CONFIGURATION_LOWER}}_${{env.BUILD_PLATFORM}} -j10
67-
72+
working-directory: ./build/${{env.PROJECT_NAME}}
73+
run: make config=${{matrix.make_config}}_${{env.BUILD_PLATFORM}} -j10
74+
75+
- name: Run tests
76+
working-directory: ./build/${{env.PROJECT_NAME}}/bin/${{env.BUILD_PLATFORM}}/${{matrix.configuration}}
77+
timeout-minutes: 10
78+
run: |
79+
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)
80+
failed=""
81+
for test in $TESTS; do
82+
./$test || failed="$failed $test"
83+
done
84+
if [ -n "$failed" ]; then echo "::error::Failed tests:$failed"; exit 1; fi

‎.github/workflows/msbuild.yml‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,22 @@ on:
2828

2929
env:
3030
PROJECT_NAME: auto_tests
31-
BUILD_CONFIGURATION: Release
3231
BUILD_PLATFORM: x64
33-
WINSDK_VER: "10.0.19041.0"
32+
TESTS: ds_tests ppmem_tests scripting_tests
33+
# Tracy needs SDK 10.0.26100 or newer (RelationProcessorDie, ETW system provider GUIDs);
34+
# it is preinstalled on the windows-2022 runner image
35+
WINSDK_VER: "10.0.26100.0"
3436

3537
permissions:
3638
contents: read
3739

3840
jobs:
3941
build:
4042
runs-on: windows-2022
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
configuration: [ Debug, Release ]
4147

4248
steps:
4349
- uses: actions/checkout@v3
@@ -50,11 +56,6 @@ jobs:
5056
with:
5157
modules-to-cache: 7Zip4PowerShell
5258

53-
- name: Setup Windows 10 SDK Action
54-
uses: GuillaumeFalourd/setup-windows10-sdk-action@v2
55-
with:
56-
sdk-version: 19041 # TODO: env
57-
5859
- name: Run PS commands
5960
shell: pwsh
6061
run: .\utils\windows_dev_prepare.ps1
@@ -70,5 +71,16 @@ jobs:
7071
working-directory: ${{env.GITHUB_WORKSPACE}}
7172
# Add additional options to the MSBuild command line here (like platform or verbosity level).
7273
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
73-
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:Platform=${{env.BUILD_PLATFORM}} build\${{env.PROJECT_NAME}}.sln
74+
run: msbuild /m /p:Configuration=${{matrix.configuration}} /p:Platform=${{env.BUILD_PLATFORM}} build\${{env.PROJECT_NAME}}\${{env.PROJECT_NAME}}.sln
7475

76+
- name: Run tests
77+
working-directory: build\${{env.PROJECT_NAME}}\bin\${{env.BUILD_PLATFORM}}\${{matrix.configuration}}
78+
shell: pwsh
79+
timeout-minutes: 10
80+
run: |
81+
$failed = @()
82+
foreach ($test in $env:TESTS.Split(' ')) {
83+
& ".\$test.exe"
84+
if ($LASTEXITCODE -ne 0) { $failed += $test }
85+
}
86+
if ($failed) { Write-Error "Failed tests: $failed"; exit 1 }

‎.gitignore‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ android-project/build/
2020
android-project/.gradle/
2121
android-project/.idea
2222

23+
build/*
24+
samples/*/build
25+
2326
src_dependency/wxWidgets/*
2427
src_dependency/openal-soft/*
2528
src_dependency/SDL2/*
2629
!src_dependency/wxWidgets/premake5.lua
2730
!src_dependency/openal-soft/premake5.lua
2831
!src_dependency/SDL2/premake5.lua
29-
src_dependency/ffmpeg/*
30-
!src_dependency/ffmpeg/premake5.lua
3132
src_dependency/slang/*
3233
!src_dependency/slang/premake5.lua
3334
src_dependency_android/SDL2/*

‎AGENTS.md‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# EQ2 Engine agent instructions
2+
3+
This is the canonical policy for every coding agent working in this repository. Tool-specific
4+
instruction files must import or point here instead of copying these rules. If guidance conflicts,
5+
the user's current request wins, followed by this file, then the subsystem documentation.
6+
7+
## Agent prerequisites and human ownership
8+
9+
- **Agents must not create or submit pull requests, or reply to reviewer questions.** Prepare local
10+
changes and validation results for the human author instead.
11+
- The human author must fully understand every submitted code change, including its behavior,
12+
evidence, compatibility constraints and validation. The human creates the pull request, answers
13+
review questions and takes responsibility for the submission; agent assistance does not transfer
14+
that responsibility.
15+
16+
## Mandatory preflight
17+
18+
Before editing:
19+
20+
1. Read this file completely.
21+
2. Run `git status --short`. This is a shared, usually dirty worktree; assume every existing change
22+
belongs to the user or another agent.
23+
3. Read `docs/building.md`, `docs/codestyle.md` and the relevant parts of `docs/architecture.md`.
24+
4. Check whether another agent is modifying the same files. Partition work or coordinate before
25+
editing overlapping code.
26+
5. At the start of each new task in a long-running session, and always right before committing,
27+
check whether this file or the docs you rely on changed since you read them
28+
(`git status --short -- AGENTS.md docs/`, `git log -1 --format=%h -- AGENTS.md docs/`).
29+
Re-read any that changed and follow the current version; other agents may update the rules
30+
in parallel sessions.
31+
32+
## Commits
33+
34+
- Commit only when the user asks. Write commit messages following `docs/commit_messages.md`.
35+
- Before running `git commit`, prepare the commit following "Review before committing" in
36+
`docs/commit_messages.md` (check the index, stage only the task files or use
37+
`git commit --only` when others have staged files), show the user the file list and the full
38+
commit message, and commit only after the user confirms.
39+
40+
## Validation
41+
42+
- TODO
43+
- run appropriate tests if test projects are available for covered source parts.
44+
45+
## Documentation
46+
47+
- TODO
48+
49+
50+

‎CLAUDE.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Claude Code repository instructions
2+
3+
@AGENTS.md
4+
5+
`AGENTS.md` is the canonical policy for this repository. Read and follow it in full before inspecting
6+
or changing source; do not maintain a separate copy of its rules here.

‎TODO.md‎

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# TODO
2+
3+
Issues noticed while writing the documentation in `docs/`. None of them has been fixed yet; each
4+
needs review by the code owner before changing.
5+
6+
## Possible bugs
7+
8+
- [ ] `core/e2core/Localize.cpp:213` — `RemoveTokensFile` calls `m_tokens.remove(it)` and then
9+
`++it` on the removed iterator (use after free). `Map::remove` returns the next iterator; the
10+
loop should continue from it.
11+
- [ ] `core/e2core/Localize.cpp:302` — `AddToken(const char*, const wchar_t*)` passes the wide
12+
string to `LocalizeConvertSymbols` through `(char*)`. The function parses it as a narrow string
13+
and stops on the second byte of the first character, so `\n` / `\t` are not converted for this
14+
overload.
15+
- [ ] `core/e2core/Localize.cpp:302`, `:314` — both `AddToken` overloads cast away `const` and
16+
modify the caller's string in place (undefined behavior for literals).
17+
- [ ] `core/e2core/Localize.cpp:160` — when `RegionalSettings` is missing, the message says
18+
"force english" but `m_language` stays empty and the `$LOCALIZE$` search path is already removed.
19+
- [ ] `public/materialsystem1/IMaterialSystem.h:235` — template `SetupDrawDefaultUP(topology,
20+
const VERT* verts, ...)` passes `&verts` (address of the local pointer) instead of `verts`.
21+
- [ ] `public/render/IDebugOverlay.h:62-63` — `DDNodeBase::nameHash` and `frameindex` are not
22+
initialized. Without `Name()` the primitive may be treated as named by
23+
`CDebugOverlay::CheckNodeLifetime` (`nameHash != 0`) and replaced by an unrelated primitive.
24+
- [ ] `framework/core/platform/eqthread.h:101`, `:162` — `CScopedMutex` and `CScopedWriteLocker`
25+
with `blocking = false` unlock in the destructor even if the lock was not acquired.
26+
- [ ] `framework/core/platform/eqatomic.h:62` — `Atomic::CompareExchangeWeak` takes `oldVal` by
27+
value, so the updated expected value is not returned to the caller.
28+
- [ ] `framework/core/platform/eqjobmanager.cpp:260` — `CEqJobManager::AllJobsCompleted` dequeues a
29+
job and enqueues it back to check the queue, which changes the queue order (and is racy with
30+
workers).
31+
- [ ] `framework/ds/Map.h:168`, `:499` — `clear()` and `remove()` read `item->next` after calling
32+
`item->~Item()`. Works in practice, but is undefined behavior; read `next` before destroying.
33+
34+
- [ ] `shared/font/FontCache.cpp:253` — `GetFamily` returns the default family for unknown names,
35+
so `GetFont(..., defaultIfNotFound = false)` never returns `nullptr` once a default font exists.
36+
37+
## Code quality
38+
39+
- [ ] `shared/font/FontCache.cpp:47` — font description loading uses the deprecated
40+
`KV_LoadFromFile`.
41+
- [ ] `shared/studio/StudioGeom.cpp:708` — `.skin` loading uses the deprecated `KV_LoadFromFile`.
42+
- [ ] `tools/fcompress/fcompress_main.cpp:390`, `:520` — config and KeyValues conversion use the
43+
deprecated `KV_LoadFromFile` / `KV_GetValue*`.
44+
- [ ] `public/egf/*.h`, `shared/egf`, tools — headers and comments still call EGF "Equilibrium
45+
Geometry Format" / "Equilibrium Graphics File"; the format is now named Entity Geometry Format.
46+
47+
- [ ] `framework/core/ConCommand.h:17` — `CMD_ARG_CONCAT` uses an undefined `i` and appends the
48+
separator once after the loop instead of between arguments. Appears unused.
49+
- [ ] `core/e2core/profiler_core.cpp:158` — `ptrace_stop` description is "Performance trace start"
50+
(copied from `ptrace_start`).
51+
- [ ] `framework/core/platform/eqthread.h:222`, `:237` — the usage comment mentions a non-existent
52+
`StartWorker()` and its worker example calls `StartThread` instead of `StartWorkerThread`.
53+
- [ ] `public/core/IEqParallelJobs.h:27` — comment mentions `JOB_FLAG_DELETE`, which does not exist
54+
(the job is created with `DeleteOnFinish`).
55+
- [ ] `framework/math/Utility.cpp:36`, `:50` — `PointToScreen` returns `true` when the point is
56+
**behind** the camera; the name suggests the opposite. Consider renaming the result or
57+
documenting it in `Utility.h`.
58+
- [ ] `core/e2core/Localize.cpp:113` — `Init` lower-cases `m_language` again after
59+
`SetLanguageName` already did it.
60+
- [ ] `core/e2core/Localize.cpp` — style does not match `docs/codestyle.md` (C-style casts,
61+
`_FindToken` reserved identifier, missing `override`, `pszDefaultToken = 0`, mixed `if(` /
62+
`if (`). Only relevant if the file is refactored.
63+
64+
## Features
65+
66+
- [ ] `tools/egfca` — generate `.skin` files (additional model skins) from the compile script, so
67+
they do not have to be written by hand.
68+
69+
## Build scripts
70+
71+
- [ ] `shared/premake5.lua:189` — `sysLib` lists `gamesys/**`, which does not exist in `shared/`.
72+
- [ ] `samples/GPUDriven/premake5.lua:26` — uses `egfLib`, which is defined only when
73+
`ENABLE_TOOLS` is on.
74+
- [ ] `utils/.premake_modules/usage` — the custom `usage` / `uses` module conflicts with the
75+
built-in usages of newer premake5 releases (they work differently), so the build is pinned to
76+
the premake5 binaries in `utils/`. Resolve the conflict (rename the module API or migrate to
77+
the built-in usages) to allow updating premake5.
78+
79+
## Documentation to verify
80+
81+
- [ ] `docs/keyvalues.md` — V3 array elements separated by whitespace (`[bottom hcenter]`) and the
82+
one-line `embed1 { embeddedFlags flag1 flag3; }` form in V2 were not verified against the parser.
83+
- [ ] `docs/public_filesystem.md` — whether `CFileSystemFind::GetPath()` returns a full path or only
84+
the entry name.
85+
- [ ] `docs/framework_math.md` — `QuadTree.h` description (Barnes-Hut style) is inferred from method
86+
names.

‎core/e2core/FileSystem.cpp‎

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <Windows.h>
1313
#include <direct.h> // _mkdir()
1414
#else
15-
#include <unistd.h> // rmdir()
15+
#include <unistd.h> // rmdir(), getcwd()
1616
#define USE_PATH_TO_FILE_MAPPING
1717
#endif
1818

@@ -684,6 +684,70 @@ EqStringRef CFileSystem::GetAbsolutePath(ESearchPath search, const char* dirOrFi
684684
return fullPath;
685685
}
686686

687+
EqStringRef CFileSystem::GetAbsoluteFullPath(ESearchPath search, const char* dirOrFileName) const
688+
{
689+
constexpr int MAX_PATH_LEN = 1024;
690+
691+
EqString fullPath = GetAbsolutePath(search, dirOrFileName);
692+
693+
#ifdef _WIN32
694+
695+
EqWString fullWPath;
696+
AnsiUnicodeConverter(fullWPath, fullPath);
697+
698+
wchar_t fullAbsWPath[MAX_PATH_LEN]{ 0 };
699+
GetFullPathNameW(fullWPath, MAX_PATH_LEN, fullAbsWPath, nullptr);
700+
701+
AnsiUnicodeConverter(fullPath, fullAbsWPath);
702+
#else
703+
// like GetFullPathName: lexical normalization, path does not have to exist
704+
if (fullPath.Length() && fullPath[0] != CORRECT_PATH_SEPARATOR)
705+
{
706+
char cwdPath[MAX_PATH_LEN];
707+
if (getcwd(cwdPath, sizeof(cwdPath)))
708+
fullPath = fnmPathCombine(cwdPath, fullPath);
709+
}
710+
711+
Array<EqStringRef> pathParts(PP_SL);
712+
int partStart = 0;
713+
for (int i = 0; i <= fullPath.Length(); ++i)
714+
{
715+
if (i < fullPath.Length() && fullPath[i] != CORRECT_PATH_SEPARATOR)
716+
continue;
717+
718+
const EqStringRef part(fullPath.ToCString() + partStart, i - partStart);
719+
partStart = i + 1;
720+
721+
if (part.Length() == 0 || part == ".")
722+
continue;
723+
724+
if (part == "..")
725+
{
726+
if (pathParts.numElem())
727+
pathParts.popBack();
728+
continue;
729+
}
730+
731+
pathParts.append(part);
732+
}
733+
734+
EqString normalizedPath;
735+
for (const EqStringRef part : pathParts)
736+
{
737+
normalizedPath.Append(CORRECT_PATH_SEPARATOR);
738+
normalizedPath.Append(part);
739+
}
740+
741+
if (!normalizedPath.Length())
742+
normalizedPath.Append(CORRECT_PATH_SEPARATOR);
743+
744+
fullPath = normalizedPath;
745+
#endif
746+
747+
// fullPath is local, return it from temp string storage
748+
return EqStringRef::GetTempString(fullPath.ToCString(), fullPath.Length());
749+
}
750+
687751
bool CFileSystem::FileRemove(const char* filename, ESearchPath search ) const
688752
{
689753
const EqStringRef path = GetAbsolutePath(search, filename);

‎core/e2core/FileSystem.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class CFileSystem : public IFileSystem
133133
bool InitNextPath(FSFindData* findData) const;
134134

135135
EqStringRef GetAbsolutePath(ESearchPath search, const char* dirOrFileName) const;
136+
EqStringRef GetAbsoluteFullPath(ESearchPath search, const char* dirOrFileName) const;
136137
EqStringRef GetSearchPath(ESearchPath search, int directoryId = -1) const;
137138

138139
using SPWalkFunc = EqFunction<bool(EqStringRef filePath, ESearchPath searchPath, const FSSearchPathInfo& spInfo, int spFlags)>;

0 commit comments

Comments
 (0)