Compare commits
2 Commits
1ed9949bf3
...
46a51e1209
| Author | SHA1 | Date | |
|---|---|---|---|
| 46a51e1209 | |||
| 55ef2cea51 |
22
Makefile
22
Makefile
@@ -52,25 +52,3 @@ configure-gba:
|
|||||||
.PHONY: configure-gba-debug
|
.PHONY: configure-gba-debug
|
||||||
configure-gba-debug:
|
configure-gba-debug:
|
||||||
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
|
${BC_CMD_SETUP_BUILD} --toolchain=deps/gbabuildcore/cmake/modules/GBA.cmake --target=gba --current_build=0 --build_type=debug --build_root=${BC_VAR_BUILD_PATH}
|
||||||
|
|
||||||
.PHONY: loc
|
|
||||||
loc:
|
|
||||||
${BC_PY3} util/scripts/loc.py \
|
|
||||||
--search-dirs \
|
|
||||||
src \
|
|
||||||
deps/ox/src \
|
|
||||||
deps/buildcore \
|
|
||||||
deps/gbabuildcore \
|
|
||||||
deps/glutils \
|
|
||||||
deps/teagba \
|
|
||||||
--include-exts \
|
|
||||||
.cpp \
|
|
||||||
.hpp \
|
|
||||||
.py \
|
|
||||||
.s \
|
|
||||||
.cmake \
|
|
||||||
--exclude-paths \
|
|
||||||
deps/teagba/src/gba_crt0.s \
|
|
||||||
src/olympic/studio/applib/src/font.cpp \
|
|
||||||
src/olympic/studio/applib/src/font.hpp \
|
|
||||||
src/nostalgia/studio/icondata.cpp
|
|
||||||
|
|||||||
5
deps/ox/src/ox/logconn/logconn.cpp
vendored
5
deps/ox/src/ox/logconn/logconn.cpp
vendored
@@ -91,7 +91,6 @@ ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LoggerConn::msgSend() noexcept {
|
void LoggerConn::msgSend() noexcept {
|
||||||
try {
|
|
||||||
while (true) {
|
while (true) {
|
||||||
std::unique_lock lk(m_waitMut);
|
std::unique_lock lk(m_waitMut);
|
||||||
m_waitCond.wait(lk);
|
m_waitCond.wait(lk);
|
||||||
@@ -110,10 +109,6 @@ void LoggerConn::msgSend() noexcept {
|
|||||||
std::ignore = send(tmp.data(), read);
|
std::ignore = send(tmp.data(), read);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (std::exception const &e) {
|
|
||||||
oxErrf("Exception in logger thread: {}\n", e.what());
|
|
||||||
oxAssert(false, "logger thread exception");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
# d2025.06.0
|
# d2025.06.0
|
||||||
|
|
||||||
* Add ability to remember recent projects in config
|
* Add ability to remember recent projects in config
|
||||||
* Fix file deletion to close file even if not active
|
|
||||||
* PaletteEditor: Add RGB key shortcuts for focusing color channels
|
* PaletteEditor: Add RGB key shortcuts for focusing color channels
|
||||||
* PaletteEditor: Add color preview to color editor
|
* PaletteEditor: Add color preview to color editor
|
||||||
* PaletteEditor: Make RGB key shortcuts work when color channel inputs are
|
|
||||||
focused
|
|
||||||
|
|
||||||
# d2025.05.2
|
# d2025.05.2
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace nostalgia::gfx {
|
namespace nostalgia::gfx {
|
||||||
|
|
||||||
RemovePageCommand::RemovePageCommand(Palette &pal, size_t const idx) noexcept:
|
RemovePageCommand::RemovePageCommand(Palette &pal, size_t idx) noexcept:
|
||||||
m_pal(pal),
|
m_pal(pal),
|
||||||
m_idx(idx) {}
|
m_idx(idx) {}
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ namespace nostalgia::gfx {
|
|||||||
|
|
||||||
UpdateColorCommand::UpdateColorCommand(
|
UpdateColorCommand::UpdateColorCommand(
|
||||||
Palette &pal,
|
Palette &pal,
|
||||||
size_t const page,
|
size_t page,
|
||||||
size_t const idx,
|
size_t idx,
|
||||||
Color16 const newColor):
|
Color16 newColor):
|
||||||
m_pal{pal},
|
m_pal(pal),
|
||||||
m_page{page},
|
m_page(page),
|
||||||
m_idx{idx},
|
m_idx(idx),
|
||||||
m_altColor{newColor} {
|
m_altColor(newColor) {
|
||||||
if (color(m_pal, m_page, m_idx) == newColor) {
|
if (color(m_pal, m_page, m_idx) == newColor) {
|
||||||
throw studio::NoChangesException();
|
throw studio::NoChangesException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,19 +13,20 @@ DeleteTilesCommand::DeleteTilesCommand(
|
|||||||
TileSheet::SubSheetIdx idx,
|
TileSheet::SubSheetIdx idx,
|
||||||
std::size_t const tileIdx,
|
std::size_t const tileIdx,
|
||||||
std::size_t const tileCnt) noexcept:
|
std::size_t const tileCnt) noexcept:
|
||||||
m_img{img},
|
m_img(img),
|
||||||
m_idx{std::move(idx)},
|
m_idx(std::move(idx)) {
|
||||||
m_deletePos{tileIdx * PixelsPerTile},
|
constexpr unsigned bytesPerTile = PixelsPerTile;
|
||||||
m_deleteSz{tileCnt * PixelsPerTile},
|
m_deletePos = tileIdx * bytesPerTile;
|
||||||
m_deletedPixels{[this] {
|
m_deleteSz = tileCnt * bytesPerTile;
|
||||||
ox::Vector<uint8_t> deletedPixels(m_deleteSz);
|
m_deletedPixels.resize(m_deleteSz);
|
||||||
// copy pixels to be erased
|
// copy pixels to be erased
|
||||||
auto const &s = getSubSheet(m_img, m_idx);
|
{
|
||||||
auto const dst = deletedPixels.begin();
|
auto &s = getSubSheet(m_img, m_idx);
|
||||||
auto const src = s.pixels.begin() + m_deletePos;
|
auto dst = m_deletedPixels.begin();
|
||||||
|
auto src = s.pixels.begin() + m_deletePos;
|
||||||
ox::copy_n(src, m_deleteSz, dst);
|
ox::copy_n(src, m_deleteSz, dst);
|
||||||
return deletedPixels;
|
}
|
||||||
}()} {}
|
}
|
||||||
|
|
||||||
ox::Error DeleteTilesCommand::redo() noexcept {
|
ox::Error DeleteTilesCommand::redo() noexcept {
|
||||||
auto &s = getSubSheet(m_img, m_idx);
|
auto &s = getSubSheet(m_img, m_idx);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ namespace nostalgia::gfx {
|
|||||||
class DeleteTilesCommand: public TileSheetCommand {
|
class DeleteTilesCommand: public TileSheetCommand {
|
||||||
private:
|
private:
|
||||||
TileSheet &m_img;
|
TileSheet &m_img;
|
||||||
TileSheet::SubSheetIdx const m_idx;
|
TileSheet::SubSheetIdx m_idx;
|
||||||
std::size_t const m_deletePos = 0;
|
std::size_t m_deletePos = 0;
|
||||||
std::size_t const m_deleteSz = 0;
|
std::size_t m_deleteSz = 0;
|
||||||
ox::Vector<uint8_t> const m_deletedPixels;
|
ox::Vector<uint8_t> m_deletedPixels = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeleteTilesCommand(
|
DeleteTilesCommand(
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ constexpr void iterateLine(ox::Point const &a, ox::Point const &b, auto const &f
|
|||||||
DrawCommand::DrawCommand(
|
DrawCommand::DrawCommand(
|
||||||
TileSheet &img,
|
TileSheet &img,
|
||||||
TileSheet::SubSheetIdx subSheetIdx,
|
TileSheet::SubSheetIdx subSheetIdx,
|
||||||
std::size_t const idx,
|
std::size_t idx,
|
||||||
int const palIdx) noexcept:
|
int const palIdx) noexcept:
|
||||||
m_img{img},
|
m_img(img),
|
||||||
m_subSheetIdx{std::move(subSheetIdx)},
|
m_subSheetIdx(std::move(subSheetIdx)),
|
||||||
m_palIdx{palIdx} {
|
m_palIdx(palIdx) {
|
||||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||||
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, idx));
|
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, idx));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ InsertTilesCommand::InsertTilesCommand(
|
|||||||
std::size_t const tileIdx,
|
std::size_t const tileIdx,
|
||||||
std::size_t const tileCnt) noexcept:
|
std::size_t const tileCnt) noexcept:
|
||||||
m_img{img},
|
m_img{img},
|
||||||
m_idx{std::move(idx)},
|
m_idx{std::move(idx)} {
|
||||||
m_insertPos{tileIdx * PixelsPerTile},
|
m_insertPos = tileIdx * PixelsPerTile;
|
||||||
m_insertCnt{tileCnt * PixelsPerTile},
|
m_insertCnt = tileCnt * PixelsPerTile;
|
||||||
m_insertedPixels{[this] {
|
m_deletedPixels.resize(m_insertCnt);
|
||||||
ox::Vector<uint8_t> insertedPixels(m_insertCnt);
|
|
||||||
// copy pixels to be erased
|
// copy pixels to be erased
|
||||||
|
{
|
||||||
auto &s = getSubSheet(m_img, m_idx);
|
auto &s = getSubSheet(m_img, m_idx);
|
||||||
auto &p = s.pixels;
|
auto &p = s.pixels;
|
||||||
auto const dst = insertedPixels.begin();
|
auto const dst = m_deletedPixels.begin();
|
||||||
auto const src = p.begin() + p.size() - m_insertCnt;
|
auto const src = p.begin() + p.size() - m_insertCnt;
|
||||||
ox::copy_n(src, m_insertCnt, dst);
|
ox::copy_n(src, m_insertCnt, dst);
|
||||||
return insertedPixels;
|
}
|
||||||
}()} {}
|
}
|
||||||
|
|
||||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ ox::Error InsertTilesCommand::undo() noexcept {
|
|||||||
auto const src = &p[srcIdx];
|
auto const src = &p[srcIdx];
|
||||||
ox::memmove(dst1, src, sz);
|
ox::memmove(dst1, src, sz);
|
||||||
}
|
}
|
||||||
ox::memcpy(dst2, m_insertedPixels.data(), m_insertedPixels.size());
|
ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ namespace nostalgia::gfx {
|
|||||||
class InsertTilesCommand: public TileSheetCommand {
|
class InsertTilesCommand: public TileSheetCommand {
|
||||||
private:
|
private:
|
||||||
TileSheet &m_img;
|
TileSheet &m_img;
|
||||||
TileSheet::SubSheetIdx const m_idx;
|
TileSheet::SubSheetIdx m_idx;
|
||||||
std::size_t const m_insertPos{};
|
std::size_t m_insertPos = 0;
|
||||||
std::size_t const m_insertCnt{};
|
std::size_t m_insertCnt = 0;
|
||||||
ox::Vector<uint8_t> const m_insertedPixels;
|
ox::Vector<uint8_t> m_deletedPixels = {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InsertTilesCommand(
|
InsertTilesCommand(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ UpdateSubSheetCommand::UpdateSubSheetCommand(
|
|||||||
m_img{img},
|
m_img{img},
|
||||||
m_idx{std::move(idx)},
|
m_idx{std::move(idx)},
|
||||||
m_sheet{getSubSheet(m_img, m_idx)} {
|
m_sheet{getSubSheet(m_img, m_idx)} {
|
||||||
|
m_sheet = getSubSheet(m_img, m_idx);
|
||||||
m_sheet.name = std::move(name);
|
m_sheet.name = std::move(name);
|
||||||
OX_THROW_ERROR(resizeSubsheet(m_sheet, {cols, rows}));
|
OX_THROW_ERROR(resizeSubsheet(m_sheet, {cols, rows}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace nostalgia::gfx {
|
|||||||
class UpdateSubSheetCommand: public TileSheetCommand {
|
class UpdateSubSheetCommand: public TileSheetCommand {
|
||||||
private:
|
private:
|
||||||
TileSheet &m_img;
|
TileSheet &m_img;
|
||||||
TileSheet::SubSheetIdx const m_idx;
|
TileSheet::SubSheetIdx m_idx;
|
||||||
TileSheet::SubSheet m_sheet;
|
TileSheet::SubSheet m_sheet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -15,11 +15,7 @@ namespace studio {
|
|||||||
|
|
||||||
AboutPopup::AboutPopup(turbine::Context &ctx) noexcept:
|
AboutPopup::AboutPopup(turbine::Context &ctx) noexcept:
|
||||||
Popup("About"),
|
Popup("About"),
|
||||||
#ifdef DEBUG
|
|
||||||
m_text{sfmt("{} [DEBUG] - {}", keelCtx(ctx).appName, olympic::appVersion)} {
|
|
||||||
#else
|
|
||||||
m_text{sfmt("{} - {}", keelCtx(ctx).appName, olympic::appVersion)} {
|
m_text{sfmt("{} - {}", keelCtx(ctx).appName, olympic::appVersion)} {
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AboutPopup::draw(Context &sctx) noexcept {
|
void AboutPopup::draw(Context &sctx) noexcept {
|
||||||
|
|||||||
@@ -114,8 +114,9 @@ static ox::Error convertStudioConfigV1ToStudioConfigV2(
|
|||||||
using StudioConfig = StudioConfigV2;
|
using StudioConfig = StudioConfigV2;
|
||||||
|
|
||||||
|
|
||||||
StudioUI::StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexcept:
|
StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept:
|
||||||
m_sctx{*this, tctx},
|
m_sctx{*this, ctx},
|
||||||
|
m_tctx{ctx},
|
||||||
m_projectDataDir{std::move(projectDataDir)} {
|
m_projectDataDir{std::move(projectDataDir)} {
|
||||||
{
|
{
|
||||||
ImFontConfig fontCfg;
|
ImFontConfig fontCfg;
|
||||||
@@ -126,7 +127,7 @@ StudioUI::StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexc
|
|||||||
// but AddFontFromMemoryTTF requires a mutable buffer.
|
// but AddFontFromMemoryTTF requires a mutable buffer.
|
||||||
// However, setting fontCfg.FontDataOwnedByAtlas ensures
|
// However, setting fontCfg.FontDataOwnedByAtlas ensures
|
||||||
// that it will still be treated as const.
|
// that it will still be treated as const.
|
||||||
// ImGui documentation recognizes that this is a bad design,
|
// ImGui documentation recognize that this is a bad design,
|
||||||
// and hopefully it will change at some point.
|
// and hopefully it will change at some point.
|
||||||
io.Fonts->AddFontFromMemoryTTF(const_cast<uint8_t*>(font.data()), static_cast<int>(font.size()), 13, &fontCfg);
|
io.Fonts->AddFontFromMemoryTTF(const_cast<uint8_t*>(font.data()), static_cast<int>(font.size()), 13, &fontCfg);
|
||||||
}
|
}
|
||||||
@@ -365,6 +366,7 @@ void StudioUI::drawTabs() noexcept {
|
|||||||
}
|
}
|
||||||
if (m_closeActiveTab) [[unlikely]] {
|
if (m_closeActiveTab) [[unlikely]] {
|
||||||
ImGui::SetTabItemClosed(e->itemDisplayName().c_str());
|
ImGui::SetTabItemClosed(e->itemDisplayName().c_str());
|
||||||
|
|
||||||
} else if (open) [[likely]] {
|
} else if (open) [[likely]] {
|
||||||
e->draw(m_sctx);
|
e->draw(m_sctx);
|
||||||
}
|
}
|
||||||
@@ -581,36 +583,24 @@ ox::Error StudioUI::handleMoveFile(ox::StringViewCR oldPath, ox::StringViewCR ne
|
|||||||
|
|
||||||
ox::Error StudioUI::handleDeleteDir(ox::StringViewCR path) noexcept {
|
ox::Error StudioUI::handleDeleteDir(ox::StringViewCR path) noexcept {
|
||||||
auto const p = sfmt("{}/", path);
|
auto const p = sfmt("{}/", path);
|
||||||
std::ignore = m_editors.erase(
|
for (auto &e : m_editors) {
|
||||||
std::remove_if(
|
|
||||||
m_editors.begin(), m_editors.end(),
|
|
||||||
[&](ox::UPtr<BaseEditor> const &e) {
|
|
||||||
if (beginsWith(e->itemPath(), p)) {
|
if (beginsWith(e->itemPath(), p)) {
|
||||||
oxLogError(closeFile(path));
|
oxLogError(closeFile(path));
|
||||||
if (e.get() != m_activeEditor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
m_closeActiveTab = true;
|
m_closeActiveTab = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
return m_projectExplorer.refreshProjectTreeModel();
|
return m_projectExplorer.refreshProjectTreeModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error StudioUI::handleDeleteFile(ox::StringViewCR path) noexcept {
|
ox::Error StudioUI::handleDeleteFile(ox::StringViewCR path) noexcept {
|
||||||
std::ignore = m_editors.erase(
|
for (auto &e : m_editors) {
|
||||||
std::remove_if(
|
|
||||||
m_editors.begin(), m_editors.end(),
|
|
||||||
[&](ox::UPtr<BaseEditor> const &e) {
|
|
||||||
if (path == e->itemPath()) {
|
if (path == e->itemPath()) {
|
||||||
oxLogError(closeFile(path));
|
oxLogError(closeFile(path));
|
||||||
if (e.get() != m_activeEditor) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
m_closeActiveTab = true;
|
m_closeActiveTab = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
return m_projectExplorer.refreshProjectTreeModel();
|
return m_projectExplorer.refreshProjectTreeModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,10 +701,10 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi
|
|||||||
}
|
}
|
||||||
OX_REQUIRE(ext, fileExt(path));
|
OX_REQUIRE(ext, fileExt(path));
|
||||||
// create Editor
|
// create Editor
|
||||||
ox::UPtr<BaseEditor> editor;
|
BaseEditor *editor = nullptr;
|
||||||
auto const err = m_editorMakers.contains(ext) ?
|
auto const err = m_editorMakers.contains(ext) ?
|
||||||
m_editorMakers[ext](path).to<ox::UPtr<BaseEditor>>().moveTo(editor) :
|
m_editorMakers[ext](path).moveTo(editor) :
|
||||||
ox::make_unique_catch<ClawEditor>(m_sctx, path).moveTo(editor);
|
ox::makeCatch<ClawEditor>(m_sctx, path).moveTo(editor);
|
||||||
if (err) {
|
if (err) {
|
||||||
if constexpr(!ox::defines::Debug) {
|
if constexpr(!ox::defines::Debug) {
|
||||||
oxErrf("Could not open Editor: {}\n", toStr(err));
|
oxErrf("Could not open Editor: {}\n", toStr(err));
|
||||||
@@ -724,11 +714,11 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool const makeActi
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
editor->closed.connect(this, &StudioUI::closeFile);
|
editor->closed.connect(this, &StudioUI::closeFile);
|
||||||
auto const &e = m_editors.emplace_back(std::move(editor));
|
m_editors.emplace_back(editor);
|
||||||
m_openFiles.emplace_back(path);
|
m_openFiles.emplace_back(path);
|
||||||
if (makeActiveTab) {
|
if (makeActiveTab) {
|
||||||
m_activeEditor = m_editors.back().value->get();
|
m_activeEditor = m_editors.back().value->get();
|
||||||
m_activeEditorUpdatePending = e.get();
|
m_activeEditorUpdatePending = editor;
|
||||||
}
|
}
|
||||||
// save to config
|
// save to config
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&path](StudioConfig &config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&path](StudioConfig &config) {
|
||||||
|
|||||||
@@ -25,12 +25,12 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
class StudioUI final: public ox::SignalHandler {
|
class StudioUI: public ox::SignalHandler {
|
||||||
friend class StudioUIDrawer;
|
friend class StudioUIDrawer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Context m_sctx;
|
Context m_sctx;
|
||||||
turbine::Context &m_tctx{m_sctx.tctx};
|
turbine::Context &m_tctx;
|
||||||
ox::String m_projectDataDir;
|
ox::String m_projectDataDir;
|
||||||
ox::UPtr<Project> m_project;
|
ox::UPtr<Project> m_project;
|
||||||
TaskRunner m_taskRunner;
|
TaskRunner m_taskRunner;
|
||||||
@@ -83,7 +83,7 @@ class StudioUI final: public ox::SignalHandler {
|
|||||||
ox::Optional<NavAction> m_navAction;
|
ox::Optional<NavAction> m_navAction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexcept;
|
explicit StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept;
|
||||||
|
|
||||||
void handleKeyEvent(turbine::Key, bool down) noexcept;
|
void handleKeyEvent(turbine::Key, bool down) noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,10 @@ namespace studio {
|
|||||||
class StudioUI;
|
class StudioUI;
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
public:
|
|
||||||
friend void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept;
|
friend void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs) noexcept;
|
||||||
friend void navigateBack(Context &ctx) noexcept;
|
friend void navigateBack(Context &ctx) noexcept;
|
||||||
friend void navigateForward(Context &ctx) noexcept;
|
friend void navigateForward(Context &ctx) noexcept;
|
||||||
friend StudioUI;
|
friend StudioUI;
|
||||||
StudioUI &ui;
|
|
||||||
Project *project = nullptr;
|
|
||||||
turbine::Context &tctx;
|
|
||||||
protected:
|
protected:
|
||||||
struct NavPath {
|
struct NavPath {
|
||||||
ox::String filePath;
|
ox::String filePath;
|
||||||
@@ -31,8 +27,12 @@ struct Context {
|
|||||||
size_t navIdx{};
|
size_t navIdx{};
|
||||||
ox::Vector<NavPath> navStack;
|
ox::Vector<NavPath> navStack;
|
||||||
std::function<void(ox::StringParam filePath, ox::StringParam navArgs)> navCallback;
|
std::function<void(ox::StringParam filePath, ox::StringParam navArgs)> navCallback;
|
||||||
|
public:
|
||||||
|
StudioUI &ui;
|
||||||
|
Project *project = nullptr;
|
||||||
|
turbine::Context &tctx;
|
||||||
Context(StudioUI &pUi, turbine::Context &pTctx) noexcept:
|
Context(StudioUI &pUi, turbine::Context &pTctx) noexcept:
|
||||||
ui{pUi}, tctx{pTctx} {}
|
ui(pUi), tctx(pTctx) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -40,11 +40,6 @@ inline keel::Context &keelCtx(Context &ctx) noexcept {
|
|||||||
return keelCtx(ctx.tctx);
|
return keelCtx(ctx.tctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline keel::Context const &keelCtx(Context const &ctx) noexcept {
|
|
||||||
return keelCtx(ctx.tctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs = "") noexcept;
|
void navigateTo(Context &ctx, ox::StringParam filePath, ox::StringParam navArgs = "") noexcept;
|
||||||
|
|
||||||
void navigateBack(Context &ctx) noexcept;
|
void navigateBack(Context &ctx) noexcept;
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
#! /usr/bin/env python3
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
def parse_args():
|
|
||||||
parser = argparse.ArgumentParser(description="Count and sort lines of code in selected files.")
|
|
||||||
parser.add_argument(
|
|
||||||
"--search-dirs", nargs="+", required=True,
|
|
||||||
help="List of directories to search (recursively)."
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--include-exts", nargs="+", required=True,
|
|
||||||
help="List of file extensions to include (e.g. .cpp .hpp .py)"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--exclude-paths", nargs="*", default=[],
|
|
||||||
help="Full file paths to exclude from counting."
|
|
||||||
)
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
args = parse_args()
|
|
||||||
include_exts = tuple(args.include_exts)
|
|
||||||
exclude_paths = {Path(p).resolve() for p in args.exclude_paths}
|
|
||||||
files = []
|
|
||||||
for base in args.search_dirs:
|
|
||||||
path = Path(base)
|
|
||||||
if path.is_dir():
|
|
||||||
for file in path.rglob("*"):
|
|
||||||
try:
|
|
||||||
resolved_file = file.resolve()
|
|
||||||
if (
|
|
||||||
file.is_file()
|
|
||||||
and file.name.endswith(include_exts)
|
|
||||||
and resolved_file not in exclude_paths
|
|
||||||
):
|
|
||||||
files.append(str(resolved_file))
|
|
||||||
except FileNotFoundError:
|
|
||||||
continue
|
|
||||||
line_counts = []
|
|
||||||
total_lines = 0
|
|
||||||
for f in files:
|
|
||||||
try:
|
|
||||||
with open(f, "r", encoding="utf-8", errors="ignore") as file:
|
|
||||||
lines = sum(1 for _ in file)
|
|
||||||
line_counts.append((lines, f))
|
|
||||||
total_lines += lines
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Failed to read {f}: {e}")
|
|
||||||
line_counts.sort()
|
|
||||||
for count, filename in line_counts:
|
|
||||||
print(f"{count:>7} {filename}")
|
|
||||||
print(f"{total_lines:>7} total")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Reference in New Issue
Block a user