@@ -6726,6 +6726,25 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
67266726 }
67276727 }
67286728
6729+ beginTable(cpType, getLabelSize("Scripts"), "script_component_header");
6730+ propertyHeader("Scripts", -1, false, false);
6731+ ImGui::Text("%zu", firstScriptComp.scripts.size());
6732+ if (drawSummaryAddButton(ICON_FA_PLUS " Add Script##script_add")) {
6733+ MultiPropertyCmd* multiCmd = new MultiPropertyCmd();
6734+ for (const Entity& entity : entities) {
6735+ ScriptComponent& sc = sceneProject->scene->getComponent<ScriptComponent>(entity);
6736+ std::vector<ScriptEntry> newScripts = sc.scripts;
6737+ ScriptEntry entry;
6738+ entry.type = ScriptType::SCRIPT_CLASS;
6739+ entry.enabled = true;
6740+ newScripts.push_back(entry);
6741+ multiCmd->addPropertyCmd<std::vector<ScriptEntry>>(project, sceneProject->id, entity, ComponentType::ScriptComponent, "scripts", newScripts);
6742+ }
6743+ multiCmd->setNoMerge();
6744+ CommandHandle::get(project->getSelectedSceneId())->addCommand(multiCmd);
6745+ }
6746+ endTable();
6747+
67296748 if (commonIndices.empty()) {
67306749 if (entities.size() > 1) {
67316750 ImGui::TextDisabled("Select a single entity to view script details");
@@ -6873,7 +6892,7 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
68736892 ImGui::OpenPopup(("Edit Script##" + std::to_string(scriptIdx)).c_str());
68746893 }
68756894 if (ImGui::IsItemHovered()) {
6876- ImGui::SetTooltip("Edit class name");
6895+ ImGui::SetTooltip("Edit script details: class name, header and source files ");
68776896 }
68786897
68796898 ImGui::PopStyleVar();
@@ -6915,50 +6934,20 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
69156934 changed = true;
69166935 }
69176936
6918- // Source Path
6919- propertyHeader("Source File", secondColSize);
6920- //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
6921- float buttonWidth = ImGui::CalcTextSize(ICON_FA_FOLDER_OPEN).x;
6922- ImGui::SetNextItemWidth(secondColSize - buttonWidth - ImGui::GetStyle().ItemSpacing.x - ImGui::GetStyle().FramePadding.x * 2.0);
6923-
6924- ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
6925- ImGui::InputText("##new_source", sourceBuffer, sizeof(sourceBuffer), ImGuiInputTextFlags_ReadOnly);
6926- ImGui::PopStyleColor();
6927- if (ImGui::IsItemHovered()) {
6928- ImGui::SetTooltip("%s", script.path.c_str());
6929- }
6930-
6931- ImGui::SameLine();
6932- if (ImGui::Button(ICON_FA_FOLDER_OPEN "##source_btn")) {
6933- fs::path fullSrcPath(script.path);
6934- if (fullSrcPath.is_relative()) fullSrcPath = projectPath / fullSrcPath;
6935- std::string selected = FileDialogs::openFileDialog(fullSrcPath.parent_path().string());
6936- if (!selected.empty()) {
6937- std::filesystem::path p(selected);
6938- std::error_code ec;
6939- std::filesystem::path rel = std::filesystem::relative(p, projectPath, ec);
6940- if (!ec && rel.string().find("..") == std::string::npos) {
6941- srcPath = rel;
6942- strncpy(sourceBuffer, rel.filename().string().c_str(), sizeof(sourceBuffer) - 1);
6943- changed = true;
6944- } else {
6945- Backend::getApp().registerAlert("Error", "File must be inside project directory.");
6946- }
6947- }
6948- }
6949- //ImGui::PopStyleVar();
6937+ float openBtnWidth = ImGui::CalcTextSize(ICON_FA_FOLDER_OPEN).x + ImGui::GetStyle().FramePadding.x * 2.0f;
6938+ float clearBtnWidth = ImGui::CalcTextSize(ICON_FA_XMARK).x + ImGui::GetStyle().FramePadding.x * 2.0f;
6939+ float btnSpacing = ImGui::GetStyle().ItemSpacing.x;
69506940
69516941 // Header Path
69526942 if (script.type != ScriptType::SCRIPT_LUA) {
69536943 propertyHeader("Header File", secondColSize);
6954- //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
6955- ImGui::SetNextItemWidth(secondColSize - buttonWidth - ImGui::GetStyle().ItemSpacing.x - ImGui::GetStyle().FramePadding.x * 2.0);
6944+ ImGui::SetNextItemWidth(secondColSize - openBtnWidth - clearBtnWidth - btnSpacing * 2.0f);
69566945
69576946 ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
69586947 ImGui::InputText("##new_header", headerBuffer, sizeof(headerBuffer), ImGuiInputTextFlags_ReadOnly);
69596948 ImGui::PopStyleColor();
6960- if (ImGui::IsItemHovered()) {
6961- ImGui::SetTooltip("%s", script.headerPath .c_str());
6949+ if (!hdrPath.empty() && ImGui::IsItemHovered()) {
6950+ ImGui::SetTooltip("%s", hdrPath.string() .c_str());
69626951 }
69636952
69646953 ImGui::SameLine();
@@ -6979,9 +6968,54 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
69796968 }
69806969 }
69816970 }
6982- //ImGui::PopStyleVar();
6971+ ImGui::SameLine();
6972+ ImGui::BeginDisabled(hdrPath.empty());
6973+ if (ImGui::Button(ICON_FA_XMARK "##header_clear")) {
6974+ hdrPath = "";
6975+ headerBuffer[0] = '\0';
6976+ changed = true;
6977+ }
6978+ ImGui::EndDisabled();
6979+ }
6980+
6981+ // Source Path
6982+ propertyHeader("Source File", secondColSize);
6983+ ImGui::SetNextItemWidth(secondColSize - openBtnWidth - clearBtnWidth - btnSpacing * 2.0f);
6984+
6985+ ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
6986+ ImGui::InputText("##new_source", sourceBuffer, sizeof(sourceBuffer), ImGuiInputTextFlags_ReadOnly);
6987+ ImGui::PopStyleColor();
6988+ if (!srcPath.empty() && ImGui::IsItemHovered()) {
6989+ ImGui::SetTooltip("%s", srcPath.string().c_str());
69836990 }
69846991
6992+ ImGui::SameLine();
6993+ if (ImGui::Button(ICON_FA_FOLDER_OPEN "##source_btn")) {
6994+ fs::path fullSrcPath(script.path);
6995+ if (fullSrcPath.is_relative()) fullSrcPath = projectPath / fullSrcPath;
6996+ std::string selected = FileDialogs::openFileDialog(fullSrcPath.parent_path().string());
6997+ if (!selected.empty()) {
6998+ std::filesystem::path p(selected);
6999+ std::error_code ec;
7000+ std::filesystem::path rel = std::filesystem::relative(p, projectPath, ec);
7001+ if (!ec && rel.string().find("..") == std::string::npos) {
7002+ srcPath = rel;
7003+ strncpy(sourceBuffer, rel.filename().string().c_str(), sizeof(sourceBuffer) - 1);
7004+ changed = true;
7005+ } else {
7006+ Backend::getApp().registerAlert("Error", "File must be inside project directory.");
7007+ }
7008+ }
7009+ }
7010+ ImGui::SameLine();
7011+ ImGui::BeginDisabled(srcPath.empty());
7012+ if (ImGui::Button(ICON_FA_XMARK "##source_clear")) {
7013+ srcPath = "";
7014+ sourceBuffer[0] = '\0';
7015+ changed = true;
7016+ }
7017+ ImGui::EndDisabled();
7018+
69857019 endTable();
69867020
69877021 if (changed) {
@@ -6997,9 +7031,20 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
69977031 newScripts[scriptIdx].path = newSource;
69987032 if (script.type != ScriptType::SCRIPT_LUA) {
69997033 newScripts[scriptIdx].headerPath = newHeader;
7034+ if (newHeader.empty()) {
7035+ newScripts[scriptIdx].properties.clear();
7036+ }
7037+ } else {
7038+ if (newSource.empty()) {
7039+ newScripts[scriptIdx].properties.clear();
7040+ }
7041+ }
7042+
7043+ const ScriptEntry& updated = newScripts[scriptIdx];
7044+ bool hasAnyPath = !updated.path.empty() || !updated.headerPath.empty();
7045+ if (hasAnyPath) {
7046+ project->updateScriptProperties(sceneProject, entity, newScripts);
70007047 }
7001-
7002- project->updateScriptProperties(sceneProject, entity, newScripts);
70037048
70047049 cmd = new PropertyCmd<std::vector<ScriptEntry>>(project, sceneProject->id, entity, ComponentType::ScriptComponent, "scripts", newScripts);
70057050 CommandHandle::get(project->getSelectedSceneId())->addCommand(cmd);
@@ -7030,8 +7075,9 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
70307075 if (ImGui::IsItemHovered()) {
70317076 if (hdrExists){
70327077 ImGui::SetTooltip("Header: %s", script.headerPath.c_str());
7078+ } else if (hasHeader) {
7079+ ImGui::SetTooltip("Header file not found");
70337080 }
7034- else ImGui::SetTooltip("Header file not found");
70357081 }
70367082 ImGui::EndDisabled();
70377083
@@ -7040,16 +7086,17 @@ void editor::Properties::drawScriptComponent(ComponentType cpType, SceneProject*
70407086 // Resolve source path
70417087 std::filesystem::path srcPath = script.path;
70427088 if (srcPath.is_relative()) srcPath = projectPath / srcPath;
7043- bool srcExists = std::filesystem::exists(srcPath);
7089+ bool srcExists = !script.path.empty() && std::filesystem::exists(srcPath);
70447090 ImGui::BeginDisabled(!srcExists);
70457091 if (ImGui::Button((ICON_FA_FILE_CODE "##open_src_" + std::to_string(scriptIdx)).c_str())) {
70467092 Backend::getApp().getCodeEditor()->openFile(srcPath.string());
70477093 }
70487094 if (ImGui::IsItemHovered()) {
70497095 if (srcExists){
70507096 ImGui::SetTooltip("Source: %s", script.path.c_str());
7097+ } else if (!script.path.empty()) {
7098+ ImGui::SetTooltip("Source file not found");
70517099 }
7052- else ImGui::SetTooltip("Source file not found");
70537100 }
70547101 ImGui::EndDisabled();
70557102
0 commit comments