Skip to content

Commit

Permalink
Release v1.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
webermm committed Mar 7, 2023
1 parent a2eef8e commit 7711416
Show file tree
Hide file tree
Showing 120 changed files with 36,428 additions and 1,267 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,28 @@ If a copy of the MPL was not distributed with this file, You can obtain one at h
-->

## [1.8.0] Free Tagging System, Lua Logging, Linkable Struct Uniforms, Misc Bugfixes
* **File version number has changed. Files saved with RaCo 1.8.0 cannot be opened by previous versions.**

### Added
* Introduced free tagging system by adding a `userTags` property to all object types.
* The user tags are independent of the normal `tags` property controlling the render setup.
* They can be accessed in the Python API using the new `getUserTags`/`setUserTags` functions analogous to the normal `setTags`/`getTags` functions.
* Added filtering by user tags to the tree views.
* A facility generating custom log messages from LuaScripts, LuaInterfaces, and LuaScriptModules using the `rl_logInfo`, `rl_logWarn`, and `rl_logError` functions has been added.
* Calling these functions will result in a log message being generated by the LogicEngine with the string argument of the function as message.
* The logging facility is enabled in normal operation in RamsesComposer but will be disabled during export. This may lead to export failing if the logging functions are called.
* Added full support for linkable struct uniforms. Instead of a flattened property structure for struct and array of struct uniforms the application now builds the same recursive property structure as for LuaScripts. This makes uniforms structs linkable as a whole.
* Added support for the lua saving mode in the export dialog and the Python API. The lua saving mode can be also specified using the '-s' command line option in the headless application.

### Fixes
* "Save As with new ID" will now change all object IDs in the saved project. It is therefore possible to use objects from both the original and the copy as external references in the same project. The `save` function of the Python API had to remove the 'setNewID' flag and doesn't support "Save As with new ID" anymore.
* Fixed missing link validity update for links starting at external objects and ending on local objects when the set of properties of the starting object has changed in the external project.
* Fixed category names for BlitPass and RenderBufferMS types in the resource view.
* Fixed crash when moving multiple interlinked objects out of a Prefab.
* Fixed Ctrl+C shortcut to consistently copy the selection from the Python Runner and the Property Browser. Removed Copy and Paste commands from Main Menu, because they are now pane-specific.


## [1.7.0] External Textures
* **File version number has changed. Files saved with RaCo 1.7.0 cannot be opened by previous versions.**

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.19)

SET(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo")

project(RaCoOS VERSION 1.7.0)
project(RaCoOS VERSION 1.8.0)

SET(RACO_RELEASE_DIRECTORY ${CMAKE_BINARY_DIR}/release)

Expand Down
54 changes: 0 additions & 54 deletions EditorApp/EditMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,10 @@
*/
#include "EditMenu.h"

#include "common_widgets/RaCoClipboard.h"
#include "object_tree_view/ObjectTreeDock.h"
#include "object_tree_view/ObjectTreeDockManager.h"
#include "object_tree_view/ObjectTreeView.h"

#include <QApplication>
#include <QShortcut>
#include <QSortFilterProxyModel>
#include <QMessageBox>

EditMenu::EditMenu(raco::application::RaCoApplication* racoApplication, raco::object_tree::view::ObjectTreeDockManager* objectTreeDockManager, QMenu* menu) : QObject{menu} {
QObject::connect(menu, &QMenu::aboutToShow, this, [this, racoApplication, objectTreeDockManager, menu]() {
Expand All @@ -39,32 +34,6 @@ EditMenu::EditMenu(raco::application::RaCoApplication* racoApplication, raco::ob
redoAction->setEnabled(racoApplication->activeRaCoProject().undoStack()->canRedo());
undoAction->setEnabled(racoApplication->activeRaCoProject().undoStack()->canUndo());
});

menu->addSeparator();

auto* copyAction = menu->addAction("Copy");
copyAction->setShortcut(QKeySequence::Copy);
auto* pasteAction = menu->addAction("Paste");
pasteAction->setShortcut(QKeySequence::Paste);
auto activeObjectTreeDockWithSelection = objectTreeDockManager->getActiveDockWithSelection();
if (!activeObjectTreeDockWithSelection) {
copyAction->setEnabled(false);
pasteAction->setEnabled(raco::RaCoClipboard::hasEditorObject());
} else {
auto focusedTreeView = activeObjectTreeDockWithSelection->getActiveTreeView();
auto selectedIndices = focusedTreeView->getSelectedIndices();
auto pasteIndex = focusedTreeView->getSelectedInsertionTargetIndex();
copyAction->setEnabled(focusedTreeView->canCopyAtIndices(selectedIndices));
pasteAction->setEnabled(focusedTreeView->canPasteIntoIndex(pasteIndex, false) || focusedTreeView->canPasteIntoIndex({}, false));
}

QObject::connect(copyAction, &QAction::triggered, [racoApplication, objectTreeDockManager]() {
globalCopyCallback(racoApplication, objectTreeDockManager);
});

QObject::connect(pasteAction, &QAction::triggered, [racoApplication, objectTreeDockManager]() {
globalPasteCallback(racoApplication, objectTreeDockManager);
});
});
QObject::connect(menu, &QMenu::aboutToHide, this, [this, menu]() {
while (menu->actions().size() > 0) {
Expand All @@ -85,26 +54,3 @@ void EditMenu::globalRedoCallback(raco::application::RaCoApplication* racoApplic
racoApplication->activeRaCoProject().undoStack()->redo();
}
}

void EditMenu::globalCopyCallback(raco::application::RaCoApplication* racoApplication, raco::object_tree::view::ObjectTreeDockManager* objectTreeDockManager) {
if (auto activeObjectTreeDockWithSelection = objectTreeDockManager->getActiveDockWithSelection()) {
auto focusedTreeView = activeObjectTreeDockWithSelection->getActiveTreeView();
focusedTreeView->globalCopyCallback();
}
}

void EditMenu::globalPasteCallback(raco::application::RaCoApplication* racoApplication, raco::object_tree::view::ObjectTreeDockManager* objectTreeDockManager) {
if (auto activeObjectTreeDockWithSelection = objectTreeDockManager->getActiveDockWithSelection()) {
auto focusedTreeView = activeObjectTreeDockWithSelection->getActiveTreeView();

focusedTreeView->globalPasteCallback(focusedTreeView->getSelectedInsertionTargetIndex());
} else {
auto copiedObjs = raco::RaCoClipboard::get();
try {
racoApplication->activeRaCoProject().commandInterface()->pasteObjects(copiedObjs);
}
catch (std::exception& error) {
// Just ignore a failed paste
}
}
}
2 changes: 0 additions & 2 deletions EditorApp/EditMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ class EditMenu final : public QObject {

static void globalUndoCallback(raco::application::RaCoApplication* racoApplication);
static void globalRedoCallback(raco::application::RaCoApplication* racoApplication);
static void globalCopyCallback(raco::application::RaCoApplication* racoApplication, raco::object_tree::view::ObjectTreeDockManager* objectTreeDockManager);
static void globalPasteCallback(raco::application::RaCoApplication* racoApplication, raco::object_tree::view::ObjectTreeDockManager* objectTreeDockManager);

private:
raco::components::Subscription sub_;
Expand Down
46 changes: 27 additions & 19 deletions EditorApp/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,16 +413,6 @@ MainWindow::MainWindow(raco::application::RaCoApplication* racoApplication, raco
EditMenu::globalRedoCallback(racoApplication_);
});

auto copyShortcut = new QShortcut(QKeySequence::Copy, this, nullptr, nullptr, Qt::ApplicationShortcut);
QObject::connect(copyShortcut, &QShortcut::activated, this, [this]() {
EditMenu::globalCopyCallback(racoApplication_, &treeDockManager_);
});

auto pasteShortcut = new QShortcut(QKeySequence::Paste, this, nullptr, nullptr, Qt::ApplicationShortcut);
QObject::connect(pasteShortcut, &QShortcut::activated, this, [this]() {
EditMenu::globalPasteCallback(racoApplication_, &treeDockManager_);
});

ui->actionSave->setShortcut(QKeySequence::Save);
ui->actionSave->setShortcutContext(Qt::ApplicationShortcut);
QObject::connect(ui->actionSave, &QAction::triggered, this, &MainWindow::saveActiveProject);
Expand Down Expand Up @@ -585,7 +575,7 @@ void MainWindow::restoreSettings() {
}
}

void MainWindow::openProject(const QString& file, int featureLevel) {
void MainWindow::openProject(const QString& file, int featureLevel, bool generateNewObjectIDs) {
auto fileString = file.toStdString();
if (!fileString.empty() && (!raco::utils::u8path(fileString).exists() || !raco::utils::u8path(fileString).userHasReadAccess())) {
QMessageBox::warning(this, "File Load Error", fmt::format("Project file {} is not available for loading.\n\nCheck whether the file at the specified path still exists and that you have read access to that file.", fileString).c_str(), QMessageBox::Close);
Expand Down Expand Up @@ -637,7 +627,7 @@ void MainWindow::openProject(const QString& file, int featureLevel) {
int loadFeatureLevel = featureLevel;
while (true) {
try {
racoApplication_->switchActiveRaCoProject(file, relinkCallback, true, loadFeatureLevel);
racoApplication_->switchActiveRaCoProject(file, relinkCallback, true, loadFeatureLevel, generateNewObjectIDs);
break;
} catch (const ExtrefError& error) {
if (auto flError = racoApplication_->getFlError()) {
Expand Down Expand Up @@ -751,14 +741,32 @@ bool MainWindow::saveAsActiveProject(bool newID) {
}
if (!newPath.endsWith(".rca")) newPath += ".rca";
std::string errorMsg;
if (racoApplication_->activeRaCoProject().saveAs(newPath, errorMsg, setProjectName, newID)) {
updateActiveProjectConnection();
updateProjectSavedConnection();
updateUpgradeMenu();
return true;
if (newID) {
if (racoApplication_->activeRaCoProject().saveAs(newPath, errorMsg, setProjectName)) {
openProject(QString::fromStdString(racoApplication_->activeProjectPath()), -1, true);
if (racoApplication_->activeRaCoProject().save(errorMsg)) {
updateActiveProjectConnection();
updateProjectSavedConnection();
updateUpgradeMenu();
return true;
} else {
updateApplicationTitle();
QMessageBox::critical(this, "Save Error", fmt::format("Can not save project: Writing the project file '{}' failed with error '{}'", racoApplication_->activeProjectPath(), errorMsg).c_str(), QMessageBox::Ok);
}
} else {
updateApplicationTitle();
QMessageBox::critical(this, "Save Error", fmt::format("Can not save project: Writing the project file '{}' failed with error '{}'", racoApplication_->activeProjectPath(), errorMsg).c_str(), QMessageBox::Ok);
}
} else {
updateApplicationTitle();
QMessageBox::critical(this, "Save Error", fmt::format("Can not save project: Writing the project file '{}' failed with error '{}'", racoApplication_->activeProjectPath(), errorMsg).c_str(), QMessageBox::Ok);
if (racoApplication_->activeRaCoProject().saveAs(newPath, errorMsg, setProjectName)) {
updateActiveProjectConnection();
updateProjectSavedConnection();
updateUpgradeMenu();
return true;
} else {
updateApplicationTitle();
QMessageBox::critical(this, "Save Error", fmt::format("Can not save project: Writing the project file '{}' failed with error '{}'", racoApplication_->activeProjectPath(), errorMsg).c_str(), QMessageBox::Ok);
}
}
} else {
QMessageBox::warning(this, "Save Error", fmt::format("Can not save project: externally referenced projects not clean.").c_str(), QMessageBox::Ok);
Expand Down
2 changes: 1 addition & 1 deletion EditorApp/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public Q_SLOTS:
void saveDockManagerCustomLayouts();

protected Q_SLOTS:
void openProject(const QString& file = {}, int featureLevel = -1);
void openProject(const QString& file = {}, int featureLevel = -1, bool generateNewObjectIDs = false);
bool saveActiveProject();
bool upgradeActiveProject(int newFeatureLevel);
bool saveAsActiveProject(bool newID = false);
Expand Down
30 changes: 26 additions & 4 deletions HeadlessApp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class Worker : public QObject {
Q_OBJECT

public:
Worker(QObject* parent, QString& projectFile, QString& exportPath, QString& pythonScriptPath, QStringList& pythonSearchPaths, bool compressExport, QStringList positionalArguments, int featureLevel)
: QObject(parent), projectFile_(projectFile), exportPath_(exportPath), pythonScriptPath_(pythonScriptPath), pythonSearchPaths_(pythonSearchPaths), compressExport_(compressExport), positionalArguments_(positionalArguments), featureLevel_(featureLevel) {
Worker(QObject* parent, QString& projectFile, QString& exportPath, QString& pythonScriptPath, QStringList& pythonSearchPaths, bool compressExport, QStringList positionalArguments, int featureLevel, raco::application::ELuaSavingMode luaSavingMode)
: QObject(parent), projectFile_(projectFile), exportPath_(exportPath), pythonScriptPath_(pythonScriptPath), pythonSearchPaths_(pythonSearchPaths), compressExport_(compressExport), positionalArguments_(positionalArguments), featureLevel_(featureLevel), luaSavingMode_(luaSavingMode) {
}

public Q_SLOTS:
Expand Down Expand Up @@ -89,7 +89,7 @@ public Q_SLOTS:
QString logicPath = exportPath_ + "." + raco::names::FILE_EXTENSION_LOGIC_EXPORT;

std::string error;
if (!app->exportProject(ramsesPath.toStdString(), logicPath.toStdString(), compressExport_, error)) {
if (!app->exportProject(ramsesPath.toStdString(), logicPath.toStdString(), compressExport_, error, false, luaSavingMode_)) {
LOG_ERROR(raco::log_system::COMMON, "error exporting to {}\n{}", ramsesPath.toStdString(), error.c_str());
exitCode_ = 1;
}
Expand All @@ -110,6 +110,7 @@ public Q_SLOTS:
bool compressExport_;
QStringList positionalArguments_;
int featureLevel_;
raco::application::ELuaSavingMode luaSavingMode_;
int exitCode_ = 0;
};

Expand Down Expand Up @@ -196,6 +197,11 @@ int main(int argc, char* argv[]) {
"Directory to add to python module search path.",
"python-path"
);
QCommandLineOption luaSavingModeOption(
QStringList() << "s"
<< "luasavingmode",
"Lua script saving mode. Possible options: source_code, byte_code, source_and_byte_code.",
"lua-saving-mode");

parser.addOption(loadProjectAction);
parser.addOption(exportProjectAction);
Expand All @@ -206,6 +212,7 @@ int main(int argc, char* argv[]) {
parser.addOption(logFileOutputOption);
parser.addOption(ramsesLogicFeatureLevel);
parser.addOption(pythonPathOption);
parser.addOption(luaSavingModeOption);

// application must be instantiated before parsing command line
QCoreApplication a(argc, argv);
Expand Down Expand Up @@ -303,7 +310,22 @@ int main(int argc, char* argv[]) {
}
}

Worker* task = new Worker(&a, projectFile, exportPath, pythonScriptPath, pythonSearchPaths, compressExport, parser.positionalArguments(), featureLevel);
auto luaSavingMode = raco::application::ELuaSavingMode::SourceCodeOnly;
if (parser.isSet(luaSavingModeOption)) {
auto option = parser.value(luaSavingModeOption);
if (option == "byte_code") {
luaSavingMode = raco::application::ELuaSavingMode::ByteCodeOnly;
} else if (option == "source_code") {
luaSavingMode = raco::application::ELuaSavingMode::SourceCodeOnly;
} else if (option == "source_and_byte_code") {
luaSavingMode = raco::application::ELuaSavingMode::SourceAndByteCode;
} else {
LOG_ERROR(raco::log_system::COMMON, fmt::format("Invalid lua saving mode: {}. Possible values are: source_code (default), byte_code, source_and_byte_code.", option.toStdString()));
exit(1);
}
}

Worker* task = new Worker(&a, projectFile, exportPath, pythonScriptPath, pythonSearchPaths, compressExport, parser.positionalArguments(), featureLevel, luaSavingMode);
QObject::connect(task, &Worker::finished, &QCoreApplication::exit);
QTimer::singleShot(0, task, &Worker::run);

Expand Down
7 changes: 7 additions & 0 deletions HeadlessApp/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ add_racocommand_test(RaCoHeadless_load_multi_file_zip "${CMAKE_CURRENT_BINARY_DI
set_tests_properties(RaCoHeadless_load_multi_file_zip PROPERTIES WILL_FAIL True)

add_racocommand_test(RaCoHeadless_load_success "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca")

add_racocommand_test(RaCoHeadless_export_lua_saving_mode_source_code_success "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca" "-e" "lua_saving_mode_source" "-s" "source_code")
add_racocommand_test(RaCoHeadless_export_lua_saving_mode_byte_code_fl2_success "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca" "-e" "lua_saving_mode_byte_fl2" "-s" "byte_code" "-f" "2")
add_racocommand_test(RaCoHeadless_export_lua_saving_mode_source_and_byte_code_fl2_success "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca" "-e" "lua_saving_mode_source_byte_fl2" "-s" "source_and_byte_code" "-f" "2")
add_racocommand_test(RaCoHeadless_export_lua_saving_mode_long_option "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca" "-e" "lua_saving_mode_long_option_source" "--luasavingmode" "source_code")
add_racocommand_test(RaCoHeadless_export_lua_saving_mode_fail "${CMAKE_CURRENT_BINARY_DIR}" "-p" "${CMAKE_SOURCE_DIR}/resources/example_scene.rca" "-e" "lua_saving_mode_fail" "-s" "invalid_setting")
set_tests_properties(RaCoHeadless_export_lua_saving_mode_fail PROPERTIES WILL_FAIL True)
Loading

0 comments on commit 7711416

Please sign in to comment.