Skip to content

Commit

Permalink
Release v1.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
webermm committed Jan 20, 2023
1 parent 7eaf7fa commit fb0a18f
Show file tree
Hide file tree
Showing 386 changed files with 26,398 additions and 1,763 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ vc140.pdb
Testing/
CMakeLists.txt.user
__pycache__/
screenshot_tests/actual
screenshot_tests/diff
screenshot_tests/exported
37 changes: 36 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ If a copy of the MPL was not distributed with this file, You can obtain one at h
<!--- Template for next release section
## [unreleased]
* **File version number has changed. Files saved with RaCo X.Y.Z cannot be opened by previous versions.**
* **Export file format has changed. Scenes exported with RaCo X.Y.Z / ramses-logic A.B.C cannot be opened by previous ramses-logic versions.**
* **Export now supports ramses-logic feature levels up to U. Scenes exported with feature level U can't be opened with ramses-logic before vX.Y.Z.**
### Known Issues
Expand All @@ -24,6 +24,41 @@ If a copy of the MPL was not distributed with this file, You can obtain one at h
-->

## [1.6.0] Skinning, Morphing, property copy/paste, modules for Lua interfaces, misc bugfixes

* **File version number has changed. Files saved with RaCo 1.6.0 cannot be opened by previous versions.**
* **Export now supports ramses-logic feature levels up to 5. Scenes exported with feature level 4 can't be opened with ramses-logic before v1.3.0. Scenes exported with feature level 5 can't be opened with ramses-logic before v1.4.1.**
* **Starting at feature level 5 `modules()` statements in LuaInterfaces are not silently ignored anymore. Upgrading a scene to feature level 5 may therefore result in errors appearing in the scene which can be remedied by removing the offending `modules()` statements or supplying a module as needed.**

### Known Issues
* Animations of rotations are currently only working correctly for single-axis rotations due to an issue in the LogicEngine.

### Added
* Added support for vertex skinning and import of skinned meshes from glTF files.
* Added basic support for morphing: morph target position and normal mesh vertex attributes and morph weight animations will now be imported from glTF files.
* Added Copy/Paste functionality to all properties, accessible through their right-click context menu.
* Available at feature level 5: Added support for lua modules used in lua interfaces.
* Added indicator for nodes visibility to SceneGraph and Prefabs view.
* Added release_headless build folder with Ramses Composer Headless. It can be shipped and run independently from Ramses Composer Editor.
* Added "MSAA off" option to Ramses preview window and remove "MSAA 1x" option. The MSAA off option uses nearest neighbor filtering.

### Changes
* Update ramses-logic from 1.3.0 to 1.4.1.
* Update ramses from 27.0.126 to 27.0.128.

### Fixes
* Fixed crash in GLTF import dialog when importing with some items deselected and then trying to import again from the same file.
* Fixed crash on startup in case oldest log file is locked by a running process.
* Restrict feature level to the maximum supported one in the GUI application on startup to avoid crash when the feature level in the ini file is too high.
* Made error message in RenderTarget with mixed multi-sampled and normal buffers more descriptive.
* Prevent Recent Files menu from force downloading OneDrive files.
* Consistently show "Export with errors" in export dialog when RaCoHeadless would not export the scene.
* Fixed broken coloring in Python runner log.
* Consistently use relative paths in the created resource uris when importing from glTF files.
* Fix file not found errors when encountering files with links in their paths. This removes the URI case-sensitivity on Windows systems.
* Fix TracePlayer unintended retention of Lua properties values between trace loads.
* The glTF mesh import has been fixed to correctly transform and normalize the normal vectors when baking all meshes in the glTF file into a single mesh object.

## [1.5.1] Bugfix release

### Changes
Expand Down
89 changes: 42 additions & 47 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,20 @@ cmake_minimum_required(VERSION 3.19)

SET(CMAKE_CONFIGURATION_TYPES "Debug;RelWithDebInfo")

project(RaCoOS VERSION 1.5.1)
project(RaCoOS VERSION 1.6.0)

SET(RACO_RELEASE_DIRECTORY ${CMAKE_BINARY_DIR}/release)

SET(HEADLESS_RELEASE_DIRECTORY ${CMAKE_BINARY_DIR}/release_headless)

# The build and deployment process for Python works differently for Linux and Windows.
# Windows:
# * RaCo builds and runs without Python being installed.
# * RaCo is build using Python 3.8.10 from third_party/python-windows/python-3.8.10-for-build.
# This is a normal full Python installation folder, all options except Debug Binaries off.
# * The build process uses the third_party/python-windows/python-3.8.10-embed-amd64 folder (downloadable from Python as the "embeddable package")
# to generate a suitable Python folder in the release folder (containing pip and virtualenv), see third_party\python-windows\CMakeLists.txt
# * On startup, RaCoHeadless will just use the Python folder "release/bin/python-3.8.10-with-pip-and-virtualenv" generated in the steps above.
# * On startup, RaCoHeadless will just use the Python folder "${HEADLESS_RELEASE_DIRECTORY}/bin/python-3.8.10-with-pip-and-virtualenv" generated in the steps above.
# * Python will be started "in isolation", so all other Python installations/environment variables on the machine will be ignored.
# Linux:
# * RaCo requires Python 3.8 to be installed for building.
Expand Down Expand Up @@ -54,6 +56,7 @@ if(WIN32)
endif()
set(PYTHON_DEPLOYMENT_FOLDER_NAME "python-${Python_VERSION}-with-pip")
set(PYTHON_DEPLOYMENT_FOLDER "${RACO_RELEASE_DIRECTORY}/bin/${PYTHON_DEPLOYMENT_FOLDER_NAME}")
set(HEADLESS_PYTHON_DEPLOYMENT_FOLDER "${HEADLESS_RELEASE_DIRECTORY}/bin/${PYTHON_DEPLOYMENT_FOLDER_NAME}")


# Configuration - where is your Qt?
Expand Down Expand Up @@ -180,34 +183,34 @@ endmacro()
#
# Create macros to copy necessary DLLs (we might be better off using the RUNTIME_OUTPUT_DIRECTORY property in a controlled manner?)
#
macro(deploy_dlls_and_strip_symbols exetarget dlltarget)
macro(deploy_dlls_and_strip_symbols exetarget dlltarget outdir)
add_custom_command(TARGET ${exetarget} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${dlltarget}> "$<TARGET_FILE_DIR:${exetarget}>"
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:${dlltarget}> "${outdir}"
)
IF(WIN32)
add_custom_command(TARGET ${exetarget} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_PDB_FILE:${dlltarget}> "$<TARGET_FILE_DIR:${exetarget}>"
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_PDB_FILE:${dlltarget}> "${outdir}"
)
ENDIF()
seperate_debug_symbols(${exetarget} "$<TARGET_FILE_DIR:${exetarget}>/$<TARGET_FILE_NAME:${dlltarget}>")
seperate_debug_symbols(${exetarget} "${outdir}/$<TARGET_FILE_NAME:${dlltarget}>")
endmacro()
macro(deploy_ramses_client_only_shared_dlls tgt)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-lib-client-only)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-logic-lib-client-only)
macro(deploy_ramses_client_only_shared_dlls tgt outdir)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-lib-client-only "${outdir}")
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-logic-lib-client-only "${outdir}")
endmacro()
macro(deploy_ramses_with_renderer_shared_dlls tgt)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-lib)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-logic-lib)
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-lib "$<TARGET_FILE_DIR:${tgt}>")
deploy_dlls_and_strip_symbols(${tgt} raco::ramses-logic-lib "$<TARGET_FILE_DIR:${tgt}>")
endmacro()
macro(deploy_headless_shared_dlls tgt)
deploy_dlls_and_strip_symbols(${tgt} openctm)
deploy_dlls_and_strip_symbols(${tgt} openctm "$<TARGET_FILE_DIR:${tgt}>")
endmacro()
macro(deploy_gui_shared_dlls tgt)
deploy_headless_shared_dlls(${tgt})
deploy_dlls_and_strip_symbols(${tgt} qtadvanceddocking)
deploy_dlls_and_strip_symbols(${tgt} qtadvanceddocking "$<TARGET_FILE_DIR:${tgt}>")
endmacro()
macro(deploy_viewer tgt)
deploy_dlls_and_strip_symbols(${tgt} ramses-logic-viewer)
deploy_dlls_and_strip_symbols(${tgt} ramses-logic-viewer "$<TARGET_FILE_DIR:${tgt}>")
endmacro()
macro(deploy_python_dlls tgt)
IF(WIN32)
Expand All @@ -216,9 +219,9 @@ macro(deploy_python_dlls tgt)
)
else()
# Make sure RaCoHeadless starts if Python is not used and Python is not installed.
add_custom_command(TARGET ${tgt} POST_BUILD
add_custom_command(TARGET ${tgt} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "/usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0" "$<TARGET_FILE_DIR:${tgt}>"
)
)
ENDIF()
endmacro()

Expand Down Expand Up @@ -275,12 +278,12 @@ if(PACKAGE_TESTS)
macro(raco_package_add_headless_test TESTNAME FILES LIBRARIES TEST_WORKING_DIRECTORY)
raco_package_add_qt_test(${TESTNAME} "${FILES}" "${LIBRARIES}" "${TEST_WORKING_DIRECTORY}")
deploy_headless_shared_dlls(${TESTNAME})
deploy_ramses_client_only_shared_dlls(${TESTNAME})
deploy_ramses_client_only_shared_dlls(${TESTNAME} "$<TARGET_FILE_DIR:${TESTNAME}>")
endmacro()
macro(raco_package_add_gui_test TESTNAME FILES LIBRARIES TEST_WORKING_DIRECTORY)
raco_package_add_qt_test(${TESTNAME} "${FILES}" "${LIBRARIES}" "${TEST_WORKING_DIRECTORY}")
deploy_gui_shared_dlls(${TESTNAME})
deploy_ramses_client_only_shared_dlls(${TESTNAME})
deploy_ramses_client_only_shared_dlls(${TESTNAME} "$<TARGET_FILE_DIR:${TESTNAME}>")
endmacro()
function(raco_package_test_resources_process TESTNAME SOURCE_DIRECTORY)
foreach(fname ${ARGN})
Expand Down Expand Up @@ -352,35 +355,26 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
endif()

#
# Create necessary files and folders in the packaged release folder
# Macros creating necessary files and folders in the packaged release folder
#
set(raco_RELEASE_ROOT_FILES
README.md
CHANGELOG.md
)

add_custom_command(OUTPUT ${RACO_RELEASE_DIRECTORY}/migrate_to_v1_0.py
MAIN_DEPENDENCY "${CMAKE_SOURCE_DIR}/third_party/ramses-logic/tools/migrate/migrate_to_v1_0.py"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/third_party/ramses-logic/tools/migrate/migrate_to_v1_0.py" "${RACO_RELEASE_DIRECTORY}/migrate_to_v1_0.py"
VERBATIM)
LIST(APPEND ROOT_FILES_OUTPUT "${RACO_RELEASE_DIRECTORY}/migrate_to_v1_0.py")

foreach(relpath ${raco_RELEASE_ROOT_FILES})
add_custom_command(OUTPUT "${RACO_RELEASE_DIRECTORY}/${relpath}"
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/${relpath}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${relpath}" "${RACO_RELEASE_DIRECTORY}/${relpath}"
VERBATIM)
LIST(APPEND ROOT_FILES_OUTPUT ${RACO_RELEASE_DIRECTORY}/${relpath})
endforeach(relpath)

ADD_CUSTOM_TARGET(RaCoPrepareReleaseFolder DEPENDS ${ROOT_FILES_OUTPUT} SOURCES ${raco_RELEASE_ROOT_FILES})
set_target_properties (RaCoPrepareReleaseFolder PROPERTIES FOLDER Packaging)

# Create default directories for configuration files and project files.
add_custom_command(TARGET RaCoPrepareReleaseFolder POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${RACO_RELEASE_DIRECTORY}/projects"
COMMAND ${CMAKE_COMMAND} -E make_directory "${RACO_RELEASE_DIRECTORY}/python"
)
macro(add_file_copy SRC_FILE DEST_FILE)
add_custom_command(OUTPUT "${DEST_FILE}"
MAIN_DEPENDENCY "${SRC_FILE}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SRC_FILE}" "${DEST_FILE}"
VERBATIM
)
endmacro()

function(create_folder_structure FILE_LIST DEST_DIR TARGET_NAME)
foreach(filepath ${FILE_LIST})
get_filename_component(filename ${filepath} NAME)
add_file_copy(${filepath} ${DEST_DIR}/${filename})
LIST(APPEND OUTPUT_FILE_LIST ${destpath})
endforeach(filepath)

add_custom_target(${TARGET_NAME} DEPENDS ${OUTPUT_FILE_LIST} SOURCES ${FILE_LIST})
set_target_properties (${TARGET_NAME} PROPERTIES FOLDER Packaging)
endfunction()

#
# Adding the subprojects
Expand All @@ -401,4 +395,5 @@ include(cmake/ramsesversions.cmake)
add_subdirectory(EditorApp)
add_subdirectory(resources)

add_subdirectory(PyAPITests)
add_subdirectory(PyAPITests)
add_subdirectory(screenshot_tests)
20 changes: 19 additions & 1 deletion EditorApp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@ target_compile_definitions( RaCoEditor PUBLIC -DRLOGIC_VERSION="${RLOGIC_VERSION
enable_warnings_as_errors(RaCoEditor)

set_target_properties(RaCoEditor PROPERTIES OUTPUT_NAME "RamsesComposer" RUNTIME_OUTPUT_DIRECTORY "${RACO_RELEASE_DIRECTORY}/bin/$<CONFIG>")

# Copy release root folder files
set(RACO_RELEASE_ROOT_FILES
${CMAKE_SOURCE_DIR}/README.md
${CMAKE_SOURCE_DIR}/CHANGELOG.md
${CMAKE_SOURCE_DIR}/third_party/ramses-logic/tools/migrate/migrate_to_v1_0.py
)

create_folder_structure("${RACO_RELEASE_ROOT_FILES}" ${RACO_RELEASE_DIRECTORY} RaCoPrepareReleaseFolder)

# Create default directories for configuration files and project files.
add_custom_command(TARGET RaCoPrepareReleaseFolder POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${RACO_RELEASE_DIRECTORY}/projects"
COMMAND ${CMAKE_COMMAND} -E make_directory "${RACO_RELEASE_DIRECTORY}/python"
)

add_dependencies(RaCoEditor RaCoResources RaCoPrepareReleaseFolder)

target_link_libraries(RaCoEditor
Expand Down Expand Up @@ -66,4 +82,6 @@ deploy_gui_shared_dlls(RaCoEditor)
deploy_ramses_with_renderer_shared_dlls(RaCoEditor)
deploy_qt(RaCoEditor)
deploy_raco_cppruntime_dlls(RaCoEditor)
deploy_viewer(RaCoEditor)
deploy_viewer(RaCoEditor)
deploy_python_dlls(RaCoEditor)
deploy_python_folder(RaCoEditor)
62 changes: 62 additions & 0 deletions EditorApp/OpenRecentMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "core/PathManager.h"
#include "log_system/log.h"
#include "utils/u8path.h"
#include <fstream>
#include <QSettings>

OpenRecentMenu::OpenRecentMenu(QWidget* parent) : QMenu{"Open &Recent", parent} {
Expand Down Expand Up @@ -43,6 +44,64 @@ void OpenRecentMenu::addRecentFile(const QString& file) {
}
}

bool isOneDriveIniFile(std::filesystem::path path) {
auto magicString = "\\OneDrive.exe";
std::ifstream in{path, std::ifstream::in | std::ifstream::binary};
std::string line;

if (in.is_open()) {
while (std::getline(in, line)) {
if (line.find(magicString) != std::string::npos) {
return true;
}
}
}

return false;
}

// Check whether specified path is on OneDrive.
bool isOneDrivePath(raco::utils::u8path path) {
auto onedriveIniFilename = "desktop.ini";

auto fsPath = std::filesystem::path(path.internalPath());

if (fsPath.is_relative()) {
// Can not analyze relative paths.
return false;
}

if (fsPath.has_filename()) {
fsPath.remove_filename();
}

// Search the directory tree up from current folder until system root folder.
while (fsPath != fsPath.parent_path()) {
auto directory = std::filesystem::directory_entry(fsPath);
if (directory.is_directory()) {
auto itBegin = std::filesystem::directory_iterator{fsPath};
auto itEnd{std::filesystem::directory_iterator{}};

// Look for OneDrive's desktop.ini file.
auto itFound = std::find_if(itBegin, itEnd, [&](const auto& directoryEntry) {
return directoryEntry.path().filename() == onedriveIniFilename;
});
if (itFound != itEnd) {
std::filesystem::path foundPath(*itFound);

if (isOneDriveIniFile(foundPath)) {
LOG_INFO(raco::log_system::COMMON, "OneDrive root found at: {}", foundPath.string());
return true;
}
}
}

fsPath = fsPath.parent_path();
}

return false;
}

void OpenRecentMenu::refreshRecentFileMenu() {
auto recentFilesStore = raco::core::PathManager::recentFilesStoreSettings();
QStringList recentFiles{recentFilesStore.value("recent_files").toStringList()};
Expand All @@ -60,6 +119,9 @@ void OpenRecentMenu::refreshRecentFileMenu() {
if (!raco::utils::u8path(fileString).exists()) {
action->setEnabled(false);
action->setText(actionText + " (unavailable)");
} else if (isOneDrivePath(raco::utils::u8path(fileString))) {
// Not touching cloud file to prevent its download.
action->setText(actionText + " (OneDrive)");
} else if (!raco::utils::u8path(fileString).userHasReadAccess()) {
action->setEnabled(false);
action->setText(actionText + " (no read access)");
Expand Down
2 changes: 1 addition & 1 deletion EditorApp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ int main(int argc, char* argv[]) {
}

raco::components::RaCoPreferences::init();
int featureLevel = raco::components::RaCoPreferences::instance().featureLevel;
int featureLevel = std::min<int>(raco::components::RaCoPreferences::instance().featureLevel, static_cast<int>(raco::ramses_base::BaseEngineBackend::maxFeatureLevel));

if (parser.isSet(ramsesLogicFeatureLevel)) {
featureLevel = parser.value(ramsesLogicFeatureLevel).toInt();
Expand Down
15 changes: 13 additions & 2 deletions EditorApp/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#include "user_types/RenderLayer.h"
#include "user_types/RenderPass.h"
#include "user_types/RenderTarget.h"
#include "user_types/Skin.h"
#include "user_types/Texture.h"
#include "user_types/Timer.h"

Expand Down Expand Up @@ -185,6 +186,14 @@ ads::CDockAreaWidget* createAndAddObjectTree(const char* title, const char* dock
: raco::object_tree::model::ObjectTreeViewDefaultModel::COLUMNINDEX_TYPE,
Qt::SortOrder::AscendingOrder);
}

// Enable Visibility column only for specific tree views.
if (title == MainWindow::DockWidgetTypes::SCENE_GRAPH || title == MainWindow::DockWidgetTypes::PREFABS) {
newTreeView->resizeColumnToContents(raco::object_tree::model::ObjectTreeViewDefaultModel::COLUMNINDEX_VISIBILITY);
} else {
newTreeView->setColumnHidden(raco::object_tree::model::ObjectTreeViewDefaultModel::COLUMNINDEX_VISIBILITY, true);
}

dockObjectView->setTreeView(newTreeView);
treeDockManager.addTreeDock(dockObjectView);
dockModel->setParent(dockObjectView);
Expand Down Expand Up @@ -235,7 +244,8 @@ ads::CDockAreaWidget* createAndAddPrefabTree(MainWindow* mainWindow, const char*
PerspectiveCamera::typeDescription.typeName,
Animation::typeDescription.typeName,
LuaScript::typeDescription.typeName,
LuaInterface::typeDescription.typeName};
LuaInterface::typeDescription.typeName,
Skin::typeDescription.typeName};

auto* model = new raco::object_tree::model::ObjectTreeViewPrefabModel(racoApplication->activeRaCoProject().commandInterface(), racoApplication->dataChangeDispatcher(), racoApplication->externalProjects(), allowedCreateableUserTypes);

Expand All @@ -255,7 +265,8 @@ ads::CDockAreaWidget* createAndAddSceneGraphTree(MainWindow* mainWindow, const c
PerspectiveCamera::typeDescription.typeName,
Animation::typeDescription.typeName,
LuaScript::typeDescription.typeName,
LuaInterface::typeDescription.typeName};
LuaInterface::typeDescription.typeName,
Skin::typeDescription.typeName};

auto* model = new raco::object_tree::model::ObjectTreeViewDefaultModel(racoApplication->activeRaCoProject().commandInterface(), racoApplication->dataChangeDispatcher(), racoApplication->externalProjects(), allowedCreateableUserTypes);
return createAndAddObjectTree(MainWindow::DockWidgetTypes::SCENE_GRAPH, dockObjName, model, new raco::object_tree::model::ObjectTreeViewDefaultSortFilterProxyModel(mainWindow, false),
Expand Down
Loading

0 comments on commit fb0a18f

Please sign in to comment.