Skip to content

Commit e8a77f8

Browse files
committed
assets window files
1 parent e419093 commit e8a77f8

4 files changed

Lines changed: 197 additions & 8 deletions

File tree

src/editor.cpp

Lines changed: 151 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ static ImGuizmo::OPERATION gizmo_mode = ImGuizmo::TRANSLATE;
1111
static int renaming_index = -1;
1212
static char rename_buf[128] = "";
1313

14+
const float icon_size = 64.0f;
15+
const float padding = 10.0f;
16+
const float cell_size = icon_size + padding;
17+
1418
void Editor::handle_input() {
1519
float speed = 0.1f;
1620
Entity* e = scene.get_selected();
@@ -40,6 +44,7 @@ void Editor::handle_input() {
4044

4145
UnloadDroppedFiles(dropped);
4246
refresh_textures(&scene);
47+
refresh_assets();
4348
}
4449

4550
}
@@ -296,21 +301,160 @@ void Editor::draw_ui() {
296301

297302
ImGui::End();
298303

304+
draw_assets_ui();
305+
}
306+
307+
void Editor::draw_assets_ui() {
299308
ImGui::SetNextWindowSize(ImVec2(1270, 165), ImGuiCond_Once);
300309
ImGui::SetNextWindowPos(ImVec2(5, 550), ImGuiCond_Once);
301310
ImGui::Begin("Assets", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
302311

303-
if (fs::is_empty("assets")) {
304-
const char* text = "Drag files here";
312+
static ImVec2 selection_start;
313+
static ImVec2 selection_end;
314+
static bool selecting = false;
315+
static int rename_target = -1;
305316

306-
ImVec2 windowSize = ImGui::GetWindowSize();
307-
ImVec2 textSize = ImGui::CalcTextSize(text);
317+
ImVec2 window_size = ImGui::GetWindowSize();
308318

309-
ImGui::SetCursorPosX((windowSize.x - textSize.x) * 0.5f);
310-
ImGui::SetCursorPosY((windowSize.y - textSize.y) * 0.5f);
319+
if (asset_entries.empty()) {
320+
const char* text = "Drag files here";
321+
ImVec2 text_size = ImGui::CalcTextSize(text);
311322

323+
ImGui::SetCursorPosX((window_size.x - text_size.x) * 0.5f);
324+
ImGui::SetCursorPosY((window_size.y - text_size.y) * 0.5f);
312325
ImGui::Text("%s", text);
326+
}
327+
328+
else {
329+
ImGui::BeginChild("AssetScroll", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysVerticalScrollbar);
330+
331+
if (ImGui::IsWindowHovered()) {
332+
if (ImGui::IsMouseClicked(0)) {
333+
selection_start = ImGui::GetMousePos();
334+
selection_end = selection_start;
335+
selecting = true;
336+
}
337+
338+
if (ImGui::IsMouseDown(0) && selecting) selection_end = ImGui::GetMousePos();
339+
if (ImGui::IsMouseReleased(0)) selecting = false;
340+
}
341+
342+
float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
343+
344+
for (int i = 0; i < asset_entries.size(); i++) {
345+
ImGui::PushID(i);
346+
ImGui::BeginGroup();
347+
348+
ImVec2 pos = ImGui::GetCursorScreenPos();
349+
ImVec2 size(icon_size, icon_size + 20.0f);
350+
351+
ImGui::InvisibleButton("asset_btn", size);
352+
353+
if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", asset_entries[i].filename.c_str());
354+
if (ImGui::IsItemClicked() && !ImGui::IsMouseDragging(0)) selected_asset_index = i;
355+
356+
if (ImGui::BeginPopupContextItem("AssetContext")) {
357+
if (ImGui::MenuItem("Delete")) {
358+
fs::remove(fs::path("assets") / asset_entries[i].filename);
359+
asset_entries.erase(asset_entries.begin() + i);
360+
361+
if (selected_asset_index == i) selected_asset_index = -1;
362+
363+
ImGui::EndPopup();
364+
ImGui::EndGroup();
365+
ImGui::PopID();
366+
break;
367+
}
368+
369+
if (ImGui::MenuItem("Rename")) {
370+
rename_target = i;
371+
size_t copied = asset_entries[i].filename.copy(rename_buf, sizeof(rename_buf) - 1);
372+
rename_buf[copied] = '\0';
373+
374+
ImGui::OpenPopup("RenameAsset");
375+
}
376+
377+
ImGui::EndPopup();
378+
}
379+
380+
bool selected = (selected_asset_index == i);
381+
382+
if (selecting && (fabs(selection_start.x - selection_end.x) > 5.0f || fabs(selection_start.y - selection_end.y) > 5.0f)) {
383+
ImVec2 min = ImVec2(std::min(selection_start.x, selection_end.x), std::min(selection_start.y, selection_end.y));
384+
ImVec2 max = ImVec2(std::max(selection_start.x, selection_end.x), std::max(selection_start.y, selection_end.y));
385+
386+
if (!(pos.x + size.x < min.x || pos.x > max.x || pos.y + size.y < min.y || pos.y > max.y)) selected = true;
387+
}
388+
389+
if (selected) {
390+
ImVec2 frame_max = ImVec2(pos.x + size.x, pos.y + size.y);
391+
ImGui::GetWindowDrawList()->AddRectFilled(pos, frame_max, IM_COL32(80, 140, 255, 150));
392+
}
393+
394+
ImGui::SetCursorScreenPos(pos);
395+
if (asset_entries[i].is_image) ImGui::Image((void*)(intptr_t)asset_entries[i].texture.id, ImVec2(icon_size, icon_size));
396+
else ImGui::Button("File", ImVec2(icon_size, icon_size));
397+
398+
ImGui::SetCursorScreenPos(ImVec2(pos.x, pos.y + icon_size));
399+
std::string label = asset_entries[i].filename;
400+
401+
if (label.size() > 12) label = label.substr(0, 9) + "...";
402+
403+
ImGui::TextWrapped("%s", label.c_str());
404+
ImGui::EndGroup();
405+
406+
float last_x2 = ImGui::GetItemRectMax().x;
407+
float next_x2 = last_x2 + ImGui::GetStyle().ItemSpacing.x + icon_size;
408+
409+
if (i + 1 < asset_entries.size() && next_x2 < window_visible_x2)ImGui::SameLine();
410+
411+
ImGui::PopID();
412+
}
413+
414+
if (selecting && (fabs(selection_start.x - selection_end.x) > 5.0f || fabs(selection_start.y - selection_end.y) > 5.0f)) {
415+
ImVec2 min = ImVec2(std::min(selection_start.x, selection_end.x), std::min(selection_start.y, selection_end.y));
416+
ImVec2 max = ImVec2(std::max(selection_start.x, selection_end.x), std::max(selection_start.y, selection_end.y));
417+
418+
ImGui::GetForegroundDrawList()->AddRectFilled(min, max, IM_COL32(80, 140, 255, 40));
419+
}
420+
421+
if (rename_target >= 0) {
422+
ImGui::OpenPopup("RenameAsset");
423+
rename_target = -2;
424+
}
425+
426+
if (rename_target == -2 && ImGui::BeginPopupModal("RenameAsset", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
427+
ImGui::InputText("##rename", rename_buf, IM_ARRAYSIZE(rename_buf));
428+
if (ImGui::Button("OK")) {
429+
if (selected_asset_index >= 0 && selected_asset_index < asset_entries.size()) {
430+
fs::path old_path = fs::path("assets") / asset_entries[selected_asset_index].filename;
431+
fs::path new_path = fs::path("assets") / rename_buf;
432+
433+
if (rename_buf[0] != '\0' && old_path != new_path && fs::exists(old_path)) {
434+
try {
435+
fs::rename(old_path, new_path);
436+
asset_entries[selected_asset_index].filename = rename_buf;
437+
}
438+
439+
catch (...) {}
440+
}
441+
}
442+
443+
rename_target = -1;
444+
ImGui::CloseCurrentPopup();
445+
}
446+
447+
ImGui::SameLine();
448+
if (ImGui::Button("Cancel")) {
449+
rename_target = -1;
450+
ImGui::CloseCurrentPopup();
451+
}
452+
453+
ImGui::EndPopup();
454+
}
455+
456+
ImGui::EndChild();
313457
}
314458

315459
ImGui::End();
316-
}
460+
}

src/headers/editor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
struct Editor {
88
Scene scene;
9+
int selected_asset_index = -1;
910

1011
void draw_ui();
12+
void draw_assets_ui();
1113
void handle_input();
1214
void draw_entity_with_texture(Entity& e);
1315
void draw_gizmo(Camera3D camera);

src/headers/tex.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,21 @@ struct TextureOption {
1313
Texture2D texture;
1414
};
1515

16+
struct AssetEntry {
17+
std::string filename;
18+
bool is_image;
19+
Texture2D texture = {0};
20+
};
21+
1622
extern std::vector<TextureOption> texture_options;
23+
extern std::vector<AssetEntry> asset_entries;
1724

1825
void load_textures();
1926
void unload_textures();
2027
void apply_texture_repeat(Entity& e);
2128
void store_uv(Entity* e);
2229
void draw_entity_with_texture(Entity& e);
2330
void refresh_textures(Scene* scene = nullptr);
31+
void load_assets();
32+
void refresh_assets();
33+
bool is_image_file(const std::filesystem::path& p);

src/tex.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
#include <unordered_set>
44

55
namespace fs = std::filesystem;
6+
67
std::vector<TextureOption> texture_options;
8+
std::vector<AssetEntry> asset_entries;
79

8-
static bool is_image_file(const fs::path& p) {
10+
bool is_image_file(const fs::path& p) {
911
std::string ext = p.extension().string();
1012
for (auto& c : ext) c = (char)tolower(c);
1113
return ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".bmp" || ext == ".tga";
@@ -202,3 +204,34 @@ void refresh_textures(Scene* scene) {
202204

203205
texture_options = std::move(next_options);
204206
}
207+
208+
void load_assets() {
209+
asset_entries.clear();
210+
if (!fs::exists("assets")) fs::create_directories("assets");
211+
212+
for (auto& entry : fs::directory_iterator("assets")) {
213+
fs::path path = entry.path();
214+
215+
AssetEntry asset_entry;
216+
asset_entry.filename = path.filename().string();
217+
asset_entry.is_image = is_image_file(path.string());
218+
219+
if (asset_entry.is_image) {
220+
asset_entry.texture = LoadTexture(path.string().c_str());
221+
}
222+
}
223+
}
224+
225+
void refresh_assets() {
226+
asset_entries.clear();
227+
if (!fs::exists("assets")) fs::create_directories("assets");
228+
229+
for (auto& entry : fs::directory_iterator("assets")) {
230+
AssetEntry a;
231+
a.filename = entry.path().filename().string();
232+
a.is_image = is_image_file(entry.path().string());
233+
234+
if (a.is_image) a.texture = LoadTexture(entry.path().string().c_str());
235+
asset_entries.push_back(a);
236+
}
237+
}

0 commit comments

Comments
 (0)