From 9ac6ba900e3f278a5d3d413d9d1e409e69a166de Mon Sep 17 00:00:00 2001 From: Nimetu Date: Fri, 3 Jan 2014 18:02:08 +0200 Subject: [PATCH] Merge --- .../src/plugins/CMakeLists.txt | 46 +- .../src/plugins/core/CMakeLists.txt | 146 +- .../plugins/landscape_editor/CMakeLists.txt | 118 +- .../plugins/landscape_editor/builder_zone.cpp | 1080 ++--- .../landscape_editor/builder_zone_base.cpp | 412 +- .../landscape_editor/builder_zone_region.cpp | 4286 ++++++++--------- .../landscape_editor/builder_zone_region.h | 214 +- .../landscape_editor/landscape_actions.cpp | 356 +- .../landscape_editor_plugin.cpp | 200 +- .../landscape_editor_window.cpp | 828 ++-- .../landscape_editor/landscape_scene.cpp | 996 ++-- .../landscape_editor/landscape_scene_base.cpp | 662 +-- .../landscape_editor/landscape_view.cpp | 508 +- .../landscape_editor/list_zones_model.cpp | 274 +- .../landscape_editor/list_zones_widget.cpp | 616 +-- .../ovqt_plugin_landscape_editor.xml | 18 +- .../landscape_editor/pixmap_database.cpp | 308 +- .../project_settings_dialog.cpp | 120 +- .../landscape_editor/snapshot_dialog.cpp | 140 +- .../landscape_editor/zone_region_editor.cpp | 362 +- .../src/plugins/world_editor/CMakeLists.txt | 140 +- .../world_editor/ovqt_plugin_world_editor.xml | 20 +- .../plugins/world_editor/primitive_item.cpp | 624 +-- .../src/plugins/world_editor/primitive_item.h | 400 +- .../plugins/world_editor/primitives_model.cpp | 654 +-- .../plugins/world_editor/primitives_model.h | 208 +- .../plugins/world_editor/primitives_view.cpp | 914 ++-- .../plugins/world_editor/primitives_view.h | 224 +- .../world_editor/project_settings_dialog.cpp | 136 +- .../world_editor/world_editor_actions.cpp | 1582 +++--- .../world_editor/world_editor_misc.cpp | 1332 ++--- .../world_editor/world_editor_plugin.cpp | 270 +- .../world_editor/world_editor_scene.cpp | 1208 ++--- .../world_editor/world_editor_scene_item.cpp | 1480 +++--- .../world_editor_settings_page.cpp | 140 +- .../world_editor/world_editor_window.cpp | 844 ++-- 36 files changed, 10933 insertions(+), 10933 deletions(-) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt index f38c15502..3e99bdc43 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/CMakeLists.txt @@ -1,23 +1,23 @@ -ADD_SUBDIRECTORY(core) -ADD_SUBDIRECTORY(example) -ADD_SUBDIRECTORY(ovqt_sheet_builder) -ADD_SUBDIRECTORY(landscape_editor) -ADD_SUBDIRECTORY(log) -ADD_SUBDIRECTORY(disp_sheet_id) -ADD_SUBDIRECTORY(object_viewer) -ADD_SUBDIRECTORY(georges_editor) - -ADD_SUBDIRECTORY(world_editor) -IF(WITH_GUI) - ADD_SUBDIRECTORY(gui_editor) -ENDIF(WITH_GUI) - -ADD_SUBDIRECTORY(translation_manager) -ADD_SUBDIRECTORY(bnp_manager) -# Note: Temporarily disabled until development continues. -#ADD_SUBDIRECTORY(zone_painter) - -# Ryzom Specific Plugins -IF(WITH_RYZOM AND WITH_RYZOM_TOOLS) - ADD_SUBDIRECTORY(mission_compiler) -ENDIF(WITH_RYZOM AND WITH_RYZOM_TOOLS) +ADD_SUBDIRECTORY(core) +ADD_SUBDIRECTORY(example) +ADD_SUBDIRECTORY(ovqt_sheet_builder) +ADD_SUBDIRECTORY(landscape_editor) +ADD_SUBDIRECTORY(log) +ADD_SUBDIRECTORY(disp_sheet_id) +ADD_SUBDIRECTORY(object_viewer) +ADD_SUBDIRECTORY(georges_editor) + +ADD_SUBDIRECTORY(world_editor) +IF(WITH_GUI) + ADD_SUBDIRECTORY(gui_editor) +ENDIF(WITH_GUI) + +ADD_SUBDIRECTORY(translation_manager) +ADD_SUBDIRECTORY(bnp_manager) +# Note: Temporarily disabled until development continues. +#ADD_SUBDIRECTORY(zone_painter) + +# Ryzom Specific Plugins +IF(WITH_RYZOM AND WITH_RYZOM_TOOLS) + ADD_SUBDIRECTORY(mission_compiler) +ENDIF(WITH_RYZOM AND WITH_RYZOM_TOOLS) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt index a2574a748..17172c488 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/core/CMakeLists.txt @@ -1,73 +1,73 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) - -FILE(GLOB SRC *.cpp *.h) -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_CORE_PLUGIN_HDR - icore.h - icontext.h - icore_listener.h - ioptions_page.h - core_plugin.h - core.h - main_window.h - menu_manager.h - context_manager.h - settings_dialog.h - search_paths_settings_page.h - general_settings_page.h - plugin_view_dialog.h -) - -SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui - plugin_view_dialog.ui - general_settings_page.ui - search_paths_settings_page.ui -) - -SET(OVQT_CORE_PLUGIN_RCS core.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) -QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) -QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) - -SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) -SOURCE_GROUP("Core Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) - -TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) - -NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) -NL_ADD_LIB_SUFFIX(ovqt_plugin_core) - -ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -IF(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ELSE(WIN32) - IF(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ELSE(WITH_INSTALL_LIBRARIES) - INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) - ENDIF(WITH_INSTALL_LIBRARIES) -ENDIF(WIN32) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) - +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_CORE_PLUGIN_HDR + icore.h + icontext.h + icore_listener.h + ioptions_page.h + core_plugin.h + core.h + main_window.h + menu_manager.h + context_manager.h + settings_dialog.h + search_paths_settings_page.h + general_settings_page.h + plugin_view_dialog.h +) + +SET(OVQT_CORE_PLUGIN_UIS settings_dialog.ui + plugin_view_dialog.ui + general_settings_page.ui + search_paths_settings_page.ui +) + +SET(OVQT_CORE_PLUGIN_RCS core.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_ADD_RESOURCES(OVQT_CORE_PLUGIN_RC_SRCS ${OVQT_CORE_PLUGIN_RCS}) +QT4_WRAP_CPP(OVQT_CORE_PLUGIN_MOC_SRC ${OVQT_CORE_PLUGIN_HDR}) +QT4_WRAP_UI(OVQT_CORE_PLUGIN_UI_HDRS ${OVQT_CORE_PLUGIN_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_CORE_PLUGIN_UIS} ${OVQT_CORE_PLUGIN_RCS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_CORE_PLUGIN_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocSrc FILES ${OVQT_CORE_PLUGIN_MOC_SRC}) +SOURCE_GROUP("Core Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_core SHARED ${SRC} ${OVQT_CORE_PLUGIN_MOC_SRC} ${OVQT_EXT_SYS_SRC} ${OVQT_CORE_PLUGIN_RC_SRCS} ${OVQT_CORE_PLUGIN_UI_HDRS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_core nelmisc ${QT_LIBRARIES}) + +NL_DEFAULT_PROPS(ovqt_plugin_core "NeL, Tools, 3D: Object Viewer Qt Plugin: Core") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_core) +NL_ADD_LIB_SUFFIX(ovqt_plugin_core) + +ADD_DEFINITIONS(-DCORE_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +IF(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ELSE(WIN32) + IF(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} ARCHIVE DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ELSE(WITH_INSTALL_LIBRARIES) + INSTALL(TARGETS ovqt_plugin_core LIBRARY DESTINATION ${NL_LIB_PREFIX} RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) + ENDIF(WITH_INSTALL_LIBRARIES) +ENDIF(WIN32) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_core.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt index 222a9c182..68970066d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/CMakeLists.txt @@ -1,59 +1,59 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES}) - -FILE(GLOB SRC *.cpp *.h) - -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_HDR landscape_editor_plugin.h - landscape_editor_window.h - landscape_scene_base.h - landscape_scene.h - list_zones_model.h - list_zones_widget.h - landscape_view.h - project_settings_dialog.h - snapshot_dialog.h -) - -SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS landscape_editor_window.ui - list_zones_widget.ui - project_settings_dialog.ui - shapshot_dialog.ui -) - -SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_RCS landscape_editor.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_ADD_RESOURCES(OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RCS}) -QT4_WRAP_CPP(OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC ${OVQT_PLUGIN_LANDSCAPE_EDITOR_HDR}) -QT4_WRAP_UI(OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS}) - -SOURCE_GROUP(QtResources FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS}) -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS) -SOURCE_GROUP("Landscape Editor Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(ovqt_plugin_landscape_editor SHARED ${SRC} - ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} - ${OVQT_EXT_SYS_SRC} - ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS} - ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS}) - -TARGET_LINK_LIBRARIES(ovqt_plugin_landscape_editor ovqt_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) - -NL_DEFAULT_PROPS(ovqt_plugin_landscape_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Landscape Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_landscape_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_landscape_editor) - -ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) -#INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES}) + +FILE(GLOB SRC *.cpp *.h) + +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_HDR landscape_editor_plugin.h + landscape_editor_window.h + landscape_scene_base.h + landscape_scene.h + list_zones_model.h + list_zones_widget.h + landscape_view.h + project_settings_dialog.h + snapshot_dialog.h +) + +SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS landscape_editor_window.ui + list_zones_widget.ui + project_settings_dialog.ui + shapshot_dialog.ui +) + +SET(OVQT_PLUGIN_LANDSCAPE_EDITOR_RCS landscape_editor.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_ADD_RESOURCES(OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RCS}) +QT4_WRAP_CPP(OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC ${OVQT_PLUGIN_LANDSCAPE_EDITOR_HDR}) +QT4_WRAP_UI(OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UIS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS) +SOURCE_GROUP("Landscape Editor Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_landscape_editor SHARED ${SRC} + ${OVQT_PLUGIN_LANDSCAPE_EDITOR_MOC_SRC} + ${OVQT_EXT_SYS_SRC} + ${OVQT_PLUGIN_LANDSCAPE_EDITOR_UI_HDRS} + ${OVQT_PLUGIN_LANDSCAPE_EDITOR_RC_SRCS}) + +TARGET_LINK_LIBRARIES(ovqt_plugin_landscape_editor ovqt_plugin_core nelmisc nel3d nelgeorges nelligo ${QT_LIBRARIES} ${QT_QTOPENGL_LIBRARY}) + +NL_DEFAULT_PROPS(ovqt_plugin_landscape_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: Landscape Editor") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_landscape_editor) +NL_ADD_LIB_SUFFIX(ovqt_plugin_landscape_editor) + +ADD_DEFINITIONS(-DLANDSCAPE_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS ovqt_plugin_landscape_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) +#INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_landscape_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp index 35e843481..a4a42259c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone.cpp @@ -1,540 +1,540 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "builder_zone.h" -#include "list_zones_widget.h" -#include "landscape_actions.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace LandscapeEditor -{ -int LandCounter = 0; - -ZoneBuilder::ZoneBuilder(LandscapeScene *landscapeScene, ListZonesWidget *listZonesWidget, QUndoStack *undoStack) - : m_currentZoneRegion(-1), - m_pixmapDatabase(0), - m_listZonesWidget(listZonesWidget), - m_landscapeScene(landscapeScene), - m_undoStack(undoStack) -{ - nlassert(m_landscapeScene); - m_pixmapDatabase = new PixmapDatabase(); - m_lastPathName = ""; -} - -ZoneBuilder::~ZoneBuilder() -{ - delete m_pixmapDatabase; -} - -bool ZoneBuilder::init(const QString &pathName, bool displayProgress) -{ - if (pathName.isEmpty()) - return false; - if (pathName != m_lastPathName) - { - m_lastPathName = pathName; - QString zoneBankPath = pathName; - zoneBankPath += "/zoneligos/"; - - // Init the ZoneBank - m_zoneBank.reset(); - if (!initZoneBank (zoneBankPath)) - { - m_zoneBank.reset(); - return false; - } - // Construct the DataBase from the ZoneBank - QString zoneBitmapPath = pathName; - zoneBitmapPath += "/zonebitmaps/"; - m_pixmapDatabase->reset(); - if (!m_pixmapDatabase->loadPixmaps(zoneBitmapPath, m_zoneBank, displayProgress)) - { - m_zoneBank.reset(); - return false; - } - } - return true; -} - -void ZoneBuilder::actionLigoTile(const LigoData &data, const ZonePosition &zonePos) -{ - if (m_undoStack == 0) - return; - - checkBeginMacro(); - // nlinfo(QString("%1 %2 %3 (%4 %5)").arg(data.zoneName.c_str()).arg(zonePos.x).arg(zonePos.y).arg(data.posX).arg(data.posY).toStdString().c_str()); - m_zonePositionList.push_back(zonePos); - m_undoStack->push(new LigoTileCommand(data, zonePos, this, m_landscapeScene)); -} - -void ZoneBuilder::actionLigoMove(uint index, sint32 deltaX, sint32 deltaY) -{ - if (m_undoStack == 0) - return; - - checkBeginMacro(); - //m_undoStack->push(new LigoMoveCommand(index, deltaX, deltaY, this)); -} - -void ZoneBuilder::actionLigoResize(uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) -{ - if (m_undoStack == 0) - return; - - checkBeginMacro(); - // nlinfo(QString("minX=%1 maxX=%2 minY=%3 maxY=%4").arg(newMinX).arg(newMaxX).arg(newMinY).arg(newMaxY).toStdString().c_str()); - m_undoStack->push(new LigoResizeCommand(index, newMinX, newMaxX, newMinY, newMaxY, this)); -} - -void ZoneBuilder::addZone(sint32 posX, sint32 posY) -{ - // Read-only mode - if ((m_listZonesWidget == 0) || (m_undoStack == 0)) - return; - - if (m_landscapeMap.empty()) - return; - - // Check zone name - std::string zoneName = m_listZonesWidget->currentZoneName().toStdString(); - if (zoneName.empty()) - return; - - BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; - builderZoneRegion->init(this); - - uint8 rot = uint8(m_listZonesWidget->currentRot()); - uint8 flip = uint8(m_listZonesWidget->currentFlip()); - - NLLIGO::CZoneBankElement *zoneBankElement = getZoneBank().getElementByZoneName(zoneName); - - m_titleAction = QString("Add zone %1,%2").arg(posX).arg(posY); - m_createdAction = false; - m_zonePositionList.clear(); - if (m_listZonesWidget->isForce()) - { - builderZoneRegion->addForce(posX, posY, rot, flip, zoneBankElement); - } - else - { - if (m_listZonesWidget->isNotPropogate()) - builderZoneRegion->addNotPropagate(posX, posY, rot, flip, zoneBankElement); - else - builderZoneRegion->add(posX, posY, rot, flip, zoneBankElement); - } - checkEndMacro(); -} - -void ZoneBuilder::addTransition(const sint32 posX, const sint32 posY) -{ - // Read-only mode - if ((m_listZonesWidget == 0) || (m_undoStack == 0)) - return; - - if (m_landscapeMap.empty()) - return; - - m_titleAction = QString("Transition zone %1,%2").arg(posX).arg(posY); - m_createdAction = false; - m_zonePositionList.clear(); - - nlinfo(QString("trans %1,%2").arg(posX).arg(posY).toStdString().c_str()); - - sint32 x = (sint32)floor(float(posX) / m_landscapeScene->cellSize()); - sint32 y = (sint32)floor(float(posY) / m_landscapeScene->cellSize()); - sint32 k; - - // Detect if we are in a transition square to switch - BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; - builderZoneRegion->init(this); - const NLLIGO::CZoneRegion &zoneRegion = currentZoneRegion()->ligoZoneRegion(); - bool bCutEdgeTouched = false; - for (uint8 transPos = 0; transPos < 4; ++transPos) - { - uint ce = zoneRegion.getCutEdge(x, y, transPos); - - if ((ce > 0) && (ce < 3)) - for (k = 0; k < 2; ++k) - { - float xTrans, yTrans; - - if ((transPos == 0) || (transPos == 1)) - { - if (ce == 1) - xTrans = m_landscapeScene->cellSize() / 3.0f; - else - xTrans = 2.0f * m_landscapeScene->cellSize() / 3.0f; - } - else - { - if (transPos == 2) - xTrans = 0; - else - xTrans = m_landscapeScene->cellSize(); - } - xTrans += x * m_landscapeScene->cellSize(); - - if ((transPos == 2) || (transPos == 3)) - { - if (ce == 1) - yTrans = m_landscapeScene->cellSize() / 3.0f; - else - yTrans = 2.0f * m_landscapeScene->cellSize() / 3.0f; - } - else - { - if (transPos == 1) - yTrans = 0; - else - yTrans = m_landscapeScene->cellSize(); - } - yTrans += y * m_landscapeScene->cellSize(); - - if ((posX >= (xTrans - m_landscapeScene->cellSize() / 12.0f)) && - (posX <= (xTrans + m_landscapeScene->cellSize() / 12.0f)) && - (posY >= (yTrans - m_landscapeScene->cellSize() / 12.0f)) && - (posY <= (yTrans + m_landscapeScene->cellSize() / 12.0f))) - { - builderZoneRegion->invertCutEdge (x, y, transPos); - bCutEdgeTouched = true; - } - ce = 3 - ce; - } - } - - // If not clicked to change the cutEdge so the user want to change the transition - if (!bCutEdgeTouched) - { - builderZoneRegion->cycleTransition (x, y); - } - checkEndMacro(); -} - -void ZoneBuilder::delZone(const sint32 posX, const sint32 posY) -{ - if ((m_listZonesWidget == 0) || (m_undoStack == 0)) - return; - - if (m_landscapeMap.empty()) - return; - - m_titleAction = QString("Del zone %1,%2").arg(posX).arg(posY); - m_createdAction = false; - - BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; - - builderZoneRegion->init(this); - builderZoneRegion->del(posX, posY); - checkEndMacro(); -} - -int ZoneBuilder::createZoneRegion() -{ - LandscapeItem landItem; - landItem.zoneRegionObject = new ZoneRegionObject(); - landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); - landItem.builderZoneRegion->init(this); - landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); - - m_landscapeMap.insert(LandCounter, landItem); - if (m_currentZoneRegion == -1) - setCurrentZoneRegion(LandCounter); - - calcMask(); - return LandCounter++; -} - -int ZoneBuilder::createZoneRegion(const QString &fileName) -{ - LandscapeItem landItem; - landItem.zoneRegionObject = new ZoneRegionObject(); - landItem.zoneRegionObject->load(fileName.toStdString()); - - if (checkOverlaps(landItem.zoneRegionObject->ligoZoneRegion())) - { - delete landItem.zoneRegionObject; - return -1; - } - landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); - landItem.builderZoneRegion->init(this); - - m_landscapeScene->addZoneRegion(landItem.zoneRegionObject->ligoZoneRegion()); - landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); - m_landscapeMap.insert(LandCounter, landItem); - - if (m_currentZoneRegion == -1) - setCurrentZoneRegion(LandCounter); - - calcMask(); - return LandCounter++; -} - -void ZoneBuilder::deleteZoneRegion(int id) -{ - if (m_landscapeMap.contains(id)) - { - if (m_landscapeMap.value(id).rectItem != 0) - delete m_landscapeMap.value(id).rectItem; - m_landscapeScene->delZoneRegion(m_landscapeMap.value(id).zoneRegionObject->ligoZoneRegion()); - delete m_landscapeMap.value(id).zoneRegionObject; - delete m_landscapeMap.value(id).builderZoneRegion; - m_landscapeMap.remove(id); - calcMask(); - } - else - nlwarning("Landscape (id %i) not found", id); -} - -void ZoneBuilder::setCurrentZoneRegion(int id) -{ - if (m_landscapeMap.contains(id)) - { - if (currentIdZoneRegion() != -1) - { - NLLIGO::CZoneRegion &ligoRegion = m_landscapeMap.value(m_currentZoneRegion).zoneRegionObject->ligoZoneRegion(); - m_landscapeMap[m_currentZoneRegion].rectItem = m_landscapeScene->createLayerBlackout(ligoRegion); - } - delete m_landscapeMap.value(id).rectItem; - m_landscapeMap[id].rectItem = 0; - m_currentZoneRegion = id; - calcMask(); - } - else - nlwarning("Landscape (id %i) not found", id); -} - -int ZoneBuilder::currentIdZoneRegion() const -{ - return m_currentZoneRegion; -} - -ZoneRegionObject *ZoneBuilder::currentZoneRegion() const -{ - ZoneRegionObject *result = 0; - if (m_landscapeMap.contains(m_currentZoneRegion)) - result = m_landscapeMap.value(m_currentZoneRegion).zoneRegionObject; - - return result; -} - -int ZoneBuilder::countZoneRegion() const -{ - return m_landscapeMap.size(); -} - -ZoneRegionObject *ZoneBuilder::zoneRegion(int id) const -{ - ZoneRegionObject *result = 0; - if (m_landscapeMap.contains(id)) - result = m_landscapeMap.value(id).zoneRegionObject; - - return result; -} - -bool ZoneBuilder::ligoData(LigoData &data, const ZonePosition &zonePos) -{ - if (m_landscapeMap.contains(zonePos.region)) - { - m_landscapeMap.value(zonePos.region).zoneRegionObject->ligoData(data, zonePos.x, zonePos.y); - return true; - } - return false; -} - -void ZoneBuilder::setLigoData(LigoData &data, const ZonePosition &zonePos) -{ - if (m_landscapeMap.contains(zonePos.region)) - m_landscapeMap.value(zonePos.region).zoneRegionObject->setLigoData(data, zonePos.x, zonePos.y); -} - -bool ZoneBuilder::initZoneBank (const QString &pathName) -{ - QDir *dir = new QDir(pathName); - QStringList filters; - filters << "*.ligozone"; - - // Find all ligozone files in dir - QStringList listFiles = dir->entryList(filters, QDir::Files); - - std::string error; - Q_FOREACH(QString file, listFiles) - { - //nlinfo(file.toStdString().c_str()); - if (!m_zoneBank.addElement((pathName + file).toStdString(), error)) - QMessageBox::critical(0, QObject::tr("Landscape editor"), QString(error.c_str()), QMessageBox::Ok); - } - delete dir; - return true; -} - -PixmapDatabase *ZoneBuilder::pixmapDatabase() const -{ - return m_pixmapDatabase; -} - -QString ZoneBuilder::dataPath() const -{ - return m_lastPathName; -} - -bool ZoneBuilder::getZoneMask(sint32 x, sint32 y) -{ - if ((x < m_minX) || (x > m_maxX) || - (y < m_minY) || (y > m_maxY)) - return true; - else - return m_zoneMask[(x - m_minX) + (y - m_minY) * (1 + m_maxX - m_minX)]; -} - -void ZoneBuilder::calcMask() -{ - sint32 x, y; - - m_minY = m_minX = 1000000; - m_maxY = m_maxX = -1000000; - - if (m_landscapeMap.size() == 0) - return; - - QMapIterator i(m_landscapeMap); - while (i.hasNext()) - { - i.next(); - const NLLIGO::CZoneRegion ®ion = i.value().zoneRegionObject->ligoZoneRegion(); - - if (m_minX > region.getMinX()) - m_minX = region.getMinX(); - if (m_minY > region.getMinY()) - m_minY = region.getMinY(); - if (m_maxX < region.getMaxX()) - m_maxX = region.getMaxX(); - if (m_maxY < region.getMaxY()) - m_maxY = region.getMaxY(); - } - - m_zoneMask.resize ((1 + m_maxX - m_minX) * (1 + m_maxY - m_minY)); - sint32 stride = (1 + m_maxX - m_minX); - for (y = m_minY; y <= m_maxY; ++y) - for (x = m_minX; x <= m_maxX; ++x) - { - m_zoneMask[x - m_minX + (y - m_minY) * stride] = true; - - QMapIterator it(m_landscapeMap); - while (it.hasNext()) - { - it.next(); - if (int(it.key()) != m_currentZoneRegion) - { - const NLLIGO::CZoneRegion ®ion = it.value().zoneRegionObject->ligoZoneRegion(); - - const std::string &rSZone = region.getName (x, y); - if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) - { - m_zoneMask[x - m_minX + (y - m_minY) * stride] = false; - } - } - } - } -} - -bool ZoneBuilder::getZoneAmongRegions(ZonePosition &zonePos, BuilderZoneRegion *builderZoneRegionFrom, sint32 x, sint32 y) -{ - QMapIterator it(m_landscapeMap); - while (it.hasNext()) - { - it.next(); - const NLLIGO::CZoneRegion ®ion = it.value().zoneRegionObject->ligoZoneRegion(); - if ((x < region.getMinX()) || (x > region.getMaxX()) || - (y < region.getMinY()) || (y > region.getMaxY())) - continue; - if (region.getName(x, y) != STRING_UNUSED) - { - builderZoneRegionFrom = it.value().builderZoneRegion; - zonePos = ZonePosition(x, y, it.key()); - return true; - } - } - - // The zone is not present in other region so it is an empty or oob zone of the current region - const NLLIGO::CZoneRegion ®ion = zoneRegion(builderZoneRegionFrom->getRegionId())->ligoZoneRegion(); - if ((x < region.getMinX()) || (x > region.getMaxX()) || - (y < region.getMinY()) || (y > region.getMaxY())) - return false; // Out Of Bound - - zonePos = ZonePosition(x, y, builderZoneRegionFrom->getRegionId()); - return true; -} - -void ZoneBuilder::checkBeginMacro() -{ - if (!m_createdAction) - { - m_createdAction = true; - m_undoStack->beginMacro(m_titleAction); - m_undoScanRegionCommand = new UndoScanRegionCommand(true, this, m_landscapeScene); - m_undoStack->push(m_undoScanRegionCommand); - } -} - -void ZoneBuilder::checkEndMacro() -{ - if (m_createdAction) - { - UndoScanRegionCommand *redoScanRegionCommand = new UndoScanRegionCommand(false, this, m_landscapeScene); - - // Sets list positions in which need apply changes - m_undoScanRegionCommand->setScanList(m_zonePositionList); - redoScanRegionCommand->setScanList(m_zonePositionList); - - // Adds command in the stack - m_undoStack->push(redoScanRegionCommand); - m_undoStack->endMacro(); - } -} - -bool ZoneBuilder::checkOverlaps(const NLLIGO::CZoneRegion &newZoneRegion) -{ - QMapIterator it(m_landscapeMap); - while (it.hasNext()) - { - it.next(); - const NLLIGO::CZoneRegion &zoneRegion = it.value().zoneRegionObject->ligoZoneRegion(); - for (sint32 y = zoneRegion.getMinY(); y <= zoneRegion.getMaxY(); ++y) - for (sint32 x = zoneRegion.getMinX(); x <= zoneRegion.getMaxX(); ++x) - { - const std::string &refZoneName = zoneRegion.getName(x, y); - if (refZoneName != STRING_UNUSED) - { - const std::string &zoneName = newZoneRegion.getName(x, y); - if ((zoneName != STRING_UNUSED) && (zoneName != STRING_OUT_OF_BOUND)) - return true; - } - } - } - return false; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "builder_zone.h" +#include "list_zones_widget.h" +#include "landscape_actions.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace LandscapeEditor +{ +int LandCounter = 0; + +ZoneBuilder::ZoneBuilder(LandscapeScene *landscapeScene, ListZonesWidget *listZonesWidget, QUndoStack *undoStack) + : m_currentZoneRegion(-1), + m_pixmapDatabase(0), + m_listZonesWidget(listZonesWidget), + m_landscapeScene(landscapeScene), + m_undoStack(undoStack) +{ + nlassert(m_landscapeScene); + m_pixmapDatabase = new PixmapDatabase(); + m_lastPathName = ""; +} + +ZoneBuilder::~ZoneBuilder() +{ + delete m_pixmapDatabase; +} + +bool ZoneBuilder::init(const QString &pathName, bool displayProgress) +{ + if (pathName.isEmpty()) + return false; + if (pathName != m_lastPathName) + { + m_lastPathName = pathName; + QString zoneBankPath = pathName; + zoneBankPath += "/zoneligos/"; + + // Init the ZoneBank + m_zoneBank.reset(); + if (!initZoneBank (zoneBankPath)) + { + m_zoneBank.reset(); + return false; + } + // Construct the DataBase from the ZoneBank + QString zoneBitmapPath = pathName; + zoneBitmapPath += "/zonebitmaps/"; + m_pixmapDatabase->reset(); + if (!m_pixmapDatabase->loadPixmaps(zoneBitmapPath, m_zoneBank, displayProgress)) + { + m_zoneBank.reset(); + return false; + } + } + return true; +} + +void ZoneBuilder::actionLigoTile(const LigoData &data, const ZonePosition &zonePos) +{ + if (m_undoStack == 0) + return; + + checkBeginMacro(); + // nlinfo(QString("%1 %2 %3 (%4 %5)").arg(data.zoneName.c_str()).arg(zonePos.x).arg(zonePos.y).arg(data.posX).arg(data.posY).toStdString().c_str()); + m_zonePositionList.push_back(zonePos); + m_undoStack->push(new LigoTileCommand(data, zonePos, this, m_landscapeScene)); +} + +void ZoneBuilder::actionLigoMove(uint index, sint32 deltaX, sint32 deltaY) +{ + if (m_undoStack == 0) + return; + + checkBeginMacro(); + //m_undoStack->push(new LigoMoveCommand(index, deltaX, deltaY, this)); +} + +void ZoneBuilder::actionLigoResize(uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + if (m_undoStack == 0) + return; + + checkBeginMacro(); + // nlinfo(QString("minX=%1 maxX=%2 minY=%3 maxY=%4").arg(newMinX).arg(newMaxX).arg(newMinY).arg(newMaxY).toStdString().c_str()); + m_undoStack->push(new LigoResizeCommand(index, newMinX, newMaxX, newMinY, newMaxY, this)); +} + +void ZoneBuilder::addZone(sint32 posX, sint32 posY) +{ + // Read-only mode + if ((m_listZonesWidget == 0) || (m_undoStack == 0)) + return; + + if (m_landscapeMap.empty()) + return; + + // Check zone name + std::string zoneName = m_listZonesWidget->currentZoneName().toStdString(); + if (zoneName.empty()) + return; + + BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; + builderZoneRegion->init(this); + + uint8 rot = uint8(m_listZonesWidget->currentRot()); + uint8 flip = uint8(m_listZonesWidget->currentFlip()); + + NLLIGO::CZoneBankElement *zoneBankElement = getZoneBank().getElementByZoneName(zoneName); + + m_titleAction = QString("Add zone %1,%2").arg(posX).arg(posY); + m_createdAction = false; + m_zonePositionList.clear(); + if (m_listZonesWidget->isForce()) + { + builderZoneRegion->addForce(posX, posY, rot, flip, zoneBankElement); + } + else + { + if (m_listZonesWidget->isNotPropogate()) + builderZoneRegion->addNotPropagate(posX, posY, rot, flip, zoneBankElement); + else + builderZoneRegion->add(posX, posY, rot, flip, zoneBankElement); + } + checkEndMacro(); +} + +void ZoneBuilder::addTransition(const sint32 posX, const sint32 posY) +{ + // Read-only mode + if ((m_listZonesWidget == 0) || (m_undoStack == 0)) + return; + + if (m_landscapeMap.empty()) + return; + + m_titleAction = QString("Transition zone %1,%2").arg(posX).arg(posY); + m_createdAction = false; + m_zonePositionList.clear(); + + nlinfo(QString("trans %1,%2").arg(posX).arg(posY).toStdString().c_str()); + + sint32 x = (sint32)floor(float(posX) / m_landscapeScene->cellSize()); + sint32 y = (sint32)floor(float(posY) / m_landscapeScene->cellSize()); + sint32 k; + + // Detect if we are in a transition square to switch + BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; + builderZoneRegion->init(this); + const NLLIGO::CZoneRegion &zoneRegion = currentZoneRegion()->ligoZoneRegion(); + bool bCutEdgeTouched = false; + for (uint8 transPos = 0; transPos < 4; ++transPos) + { + uint ce = zoneRegion.getCutEdge(x, y, transPos); + + if ((ce > 0) && (ce < 3)) + for (k = 0; k < 2; ++k) + { + float xTrans, yTrans; + + if ((transPos == 0) || (transPos == 1)) + { + if (ce == 1) + xTrans = m_landscapeScene->cellSize() / 3.0f; + else + xTrans = 2.0f * m_landscapeScene->cellSize() / 3.0f; + } + else + { + if (transPos == 2) + xTrans = 0; + else + xTrans = m_landscapeScene->cellSize(); + } + xTrans += x * m_landscapeScene->cellSize(); + + if ((transPos == 2) || (transPos == 3)) + { + if (ce == 1) + yTrans = m_landscapeScene->cellSize() / 3.0f; + else + yTrans = 2.0f * m_landscapeScene->cellSize() / 3.0f; + } + else + { + if (transPos == 1) + yTrans = 0; + else + yTrans = m_landscapeScene->cellSize(); + } + yTrans += y * m_landscapeScene->cellSize(); + + if ((posX >= (xTrans - m_landscapeScene->cellSize() / 12.0f)) && + (posX <= (xTrans + m_landscapeScene->cellSize() / 12.0f)) && + (posY >= (yTrans - m_landscapeScene->cellSize() / 12.0f)) && + (posY <= (yTrans + m_landscapeScene->cellSize() / 12.0f))) + { + builderZoneRegion->invertCutEdge (x, y, transPos); + bCutEdgeTouched = true; + } + ce = 3 - ce; + } + } + + // If not clicked to change the cutEdge so the user want to change the transition + if (!bCutEdgeTouched) + { + builderZoneRegion->cycleTransition (x, y); + } + checkEndMacro(); +} + +void ZoneBuilder::delZone(const sint32 posX, const sint32 posY) +{ + if ((m_listZonesWidget == 0) || (m_undoStack == 0)) + return; + + if (m_landscapeMap.empty()) + return; + + m_titleAction = QString("Del zone %1,%2").arg(posX).arg(posY); + m_createdAction = false; + + BuilderZoneRegion *builderZoneRegion = m_landscapeMap.value(m_currentZoneRegion).builderZoneRegion; + + builderZoneRegion->init(this); + builderZoneRegion->del(posX, posY); + checkEndMacro(); +} + +int ZoneBuilder::createZoneRegion() +{ + LandscapeItem landItem; + landItem.zoneRegionObject = new ZoneRegionObject(); + landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); + landItem.builderZoneRegion->init(this); + landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); + + m_landscapeMap.insert(LandCounter, landItem); + if (m_currentZoneRegion == -1) + setCurrentZoneRegion(LandCounter); + + calcMask(); + return LandCounter++; +} + +int ZoneBuilder::createZoneRegion(const QString &fileName) +{ + LandscapeItem landItem; + landItem.zoneRegionObject = new ZoneRegionObject(); + landItem.zoneRegionObject->load(fileName.toStdString()); + + if (checkOverlaps(landItem.zoneRegionObject->ligoZoneRegion())) + { + delete landItem.zoneRegionObject; + return -1; + } + landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); + landItem.builderZoneRegion->init(this); + + m_landscapeScene->addZoneRegion(landItem.zoneRegionObject->ligoZoneRegion()); + landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); + m_landscapeMap.insert(LandCounter, landItem); + + if (m_currentZoneRegion == -1) + setCurrentZoneRegion(LandCounter); + + calcMask(); + return LandCounter++; +} + +void ZoneBuilder::deleteZoneRegion(int id) +{ + if (m_landscapeMap.contains(id)) + { + if (m_landscapeMap.value(id).rectItem != 0) + delete m_landscapeMap.value(id).rectItem; + m_landscapeScene->delZoneRegion(m_landscapeMap.value(id).zoneRegionObject->ligoZoneRegion()); + delete m_landscapeMap.value(id).zoneRegionObject; + delete m_landscapeMap.value(id).builderZoneRegion; + m_landscapeMap.remove(id); + calcMask(); + } + else + nlwarning("Landscape (id %i) not found", id); +} + +void ZoneBuilder::setCurrentZoneRegion(int id) +{ + if (m_landscapeMap.contains(id)) + { + if (currentIdZoneRegion() != -1) + { + NLLIGO::CZoneRegion &ligoRegion = m_landscapeMap.value(m_currentZoneRegion).zoneRegionObject->ligoZoneRegion(); + m_landscapeMap[m_currentZoneRegion].rectItem = m_landscapeScene->createLayerBlackout(ligoRegion); + } + delete m_landscapeMap.value(id).rectItem; + m_landscapeMap[id].rectItem = 0; + m_currentZoneRegion = id; + calcMask(); + } + else + nlwarning("Landscape (id %i) not found", id); +} + +int ZoneBuilder::currentIdZoneRegion() const +{ + return m_currentZoneRegion; +} + +ZoneRegionObject *ZoneBuilder::currentZoneRegion() const +{ + ZoneRegionObject *result = 0; + if (m_landscapeMap.contains(m_currentZoneRegion)) + result = m_landscapeMap.value(m_currentZoneRegion).zoneRegionObject; + + return result; +} + +int ZoneBuilder::countZoneRegion() const +{ + return m_landscapeMap.size(); +} + +ZoneRegionObject *ZoneBuilder::zoneRegion(int id) const +{ + ZoneRegionObject *result = 0; + if (m_landscapeMap.contains(id)) + result = m_landscapeMap.value(id).zoneRegionObject; + + return result; +} + +bool ZoneBuilder::ligoData(LigoData &data, const ZonePosition &zonePos) +{ + if (m_landscapeMap.contains(zonePos.region)) + { + m_landscapeMap.value(zonePos.region).zoneRegionObject->ligoData(data, zonePos.x, zonePos.y); + return true; + } + return false; +} + +void ZoneBuilder::setLigoData(LigoData &data, const ZonePosition &zonePos) +{ + if (m_landscapeMap.contains(zonePos.region)) + m_landscapeMap.value(zonePos.region).zoneRegionObject->setLigoData(data, zonePos.x, zonePos.y); +} + +bool ZoneBuilder::initZoneBank (const QString &pathName) +{ + QDir *dir = new QDir(pathName); + QStringList filters; + filters << "*.ligozone"; + + // Find all ligozone files in dir + QStringList listFiles = dir->entryList(filters, QDir::Files); + + std::string error; + Q_FOREACH(QString file, listFiles) + { + //nlinfo(file.toStdString().c_str()); + if (!m_zoneBank.addElement((pathName + file).toStdString(), error)) + QMessageBox::critical(0, QObject::tr("Landscape editor"), QString(error.c_str()), QMessageBox::Ok); + } + delete dir; + return true; +} + +PixmapDatabase *ZoneBuilder::pixmapDatabase() const +{ + return m_pixmapDatabase; +} + +QString ZoneBuilder::dataPath() const +{ + return m_lastPathName; +} + +bool ZoneBuilder::getZoneMask(sint32 x, sint32 y) +{ + if ((x < m_minX) || (x > m_maxX) || + (y < m_minY) || (y > m_maxY)) + return true; + else + return m_zoneMask[(x - m_minX) + (y - m_minY) * (1 + m_maxX - m_minX)]; +} + +void ZoneBuilder::calcMask() +{ + sint32 x, y; + + m_minY = m_minX = 1000000; + m_maxY = m_maxX = -1000000; + + if (m_landscapeMap.size() == 0) + return; + + QMapIterator i(m_landscapeMap); + while (i.hasNext()) + { + i.next(); + const NLLIGO::CZoneRegion ®ion = i.value().zoneRegionObject->ligoZoneRegion(); + + if (m_minX > region.getMinX()) + m_minX = region.getMinX(); + if (m_minY > region.getMinY()) + m_minY = region.getMinY(); + if (m_maxX < region.getMaxX()) + m_maxX = region.getMaxX(); + if (m_maxY < region.getMaxY()) + m_maxY = region.getMaxY(); + } + + m_zoneMask.resize ((1 + m_maxX - m_minX) * (1 + m_maxY - m_minY)); + sint32 stride = (1 + m_maxX - m_minX); + for (y = m_minY; y <= m_maxY; ++y) + for (x = m_minX; x <= m_maxX; ++x) + { + m_zoneMask[x - m_minX + (y - m_minY) * stride] = true; + + QMapIterator it(m_landscapeMap); + while (it.hasNext()) + { + it.next(); + if (int(it.key()) != m_currentZoneRegion) + { + const NLLIGO::CZoneRegion ®ion = it.value().zoneRegionObject->ligoZoneRegion(); + + const std::string &rSZone = region.getName (x, y); + if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) + { + m_zoneMask[x - m_minX + (y - m_minY) * stride] = false; + } + } + } + } +} + +bool ZoneBuilder::getZoneAmongRegions(ZonePosition &zonePos, BuilderZoneRegion *builderZoneRegionFrom, sint32 x, sint32 y) +{ + QMapIterator it(m_landscapeMap); + while (it.hasNext()) + { + it.next(); + const NLLIGO::CZoneRegion ®ion = it.value().zoneRegionObject->ligoZoneRegion(); + if ((x < region.getMinX()) || (x > region.getMaxX()) || + (y < region.getMinY()) || (y > region.getMaxY())) + continue; + if (region.getName(x, y) != STRING_UNUSED) + { + builderZoneRegionFrom = it.value().builderZoneRegion; + zonePos = ZonePosition(x, y, it.key()); + return true; + } + } + + // The zone is not present in other region so it is an empty or oob zone of the current region + const NLLIGO::CZoneRegion ®ion = zoneRegion(builderZoneRegionFrom->getRegionId())->ligoZoneRegion(); + if ((x < region.getMinX()) || (x > region.getMaxX()) || + (y < region.getMinY()) || (y > region.getMaxY())) + return false; // Out Of Bound + + zonePos = ZonePosition(x, y, builderZoneRegionFrom->getRegionId()); + return true; +} + +void ZoneBuilder::checkBeginMacro() +{ + if (!m_createdAction) + { + m_createdAction = true; + m_undoStack->beginMacro(m_titleAction); + m_undoScanRegionCommand = new UndoScanRegionCommand(true, this, m_landscapeScene); + m_undoStack->push(m_undoScanRegionCommand); + } +} + +void ZoneBuilder::checkEndMacro() +{ + if (m_createdAction) + { + UndoScanRegionCommand *redoScanRegionCommand = new UndoScanRegionCommand(false, this, m_landscapeScene); + + // Sets list positions in which need apply changes + m_undoScanRegionCommand->setScanList(m_zonePositionList); + redoScanRegionCommand->setScanList(m_zonePositionList); + + // Adds command in the stack + m_undoStack->push(redoScanRegionCommand); + m_undoStack->endMacro(); + } +} + +bool ZoneBuilder::checkOverlaps(const NLLIGO::CZoneRegion &newZoneRegion) +{ + QMapIterator it(m_landscapeMap); + while (it.hasNext()) + { + it.next(); + const NLLIGO::CZoneRegion &zoneRegion = it.value().zoneRegionObject->ligoZoneRegion(); + for (sint32 y = zoneRegion.getMinY(); y <= zoneRegion.getMaxY(); ++y) + for (sint32 x = zoneRegion.getMinX(); x <= zoneRegion.getMaxX(); ++x) + { + const std::string &refZoneName = zoneRegion.getName(x, y); + if (refZoneName != STRING_UNUSED) + { + const std::string &zoneName = newZoneRegion.getName(x, y); + if ((zoneName != STRING_UNUSED) && (zoneName != STRING_OUT_OF_BOUND)) + return true; + } + } + } + return false; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp index 958aee640..63f246df3 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_base.cpp @@ -1,206 +1,206 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "builder_zone_base.h" -#include "landscape_scene_base.h" -#include "zone_region_editor.h" -#include "pixmap_database.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace LandscapeEditor -{ -int NewLandId = 0; - -ZoneBuilderBase::ZoneBuilderBase(LandscapeSceneBase *landscapeScene) - : m_pixmapDatabase(0), - m_landscapeSceneBase(landscapeScene) -{ - nlassert(m_landscapeSceneBase); - m_pixmapDatabase = new PixmapDatabase(); - m_lastPathName = ""; -} - -ZoneBuilderBase::~ZoneBuilderBase() -{ - delete m_pixmapDatabase; -} - -bool ZoneBuilderBase::init(const QString &pathName, bool displayProgress) -{ - if (pathName.isEmpty()) - return false; - if (pathName != m_lastPathName) - { - m_lastPathName = pathName; - QString zoneBankPath = pathName; - zoneBankPath += "/zoneligos/"; - - // Init the ZoneBank - m_zoneBank.reset(); - if (!initZoneBank (zoneBankPath)) - { - m_zoneBank.reset(); - return false; - } - // Construct the DataBase from the ZoneBank - QString zoneBitmapPath = pathName; - zoneBitmapPath += "/zonebitmaps/"; - m_pixmapDatabase->reset(); - if (!m_pixmapDatabase->loadPixmaps(zoneBitmapPath, m_zoneBank, displayProgress)) - { - m_zoneBank.reset(); - return false; - } - } - return true; -} - -int ZoneBuilderBase::loadZoneRegion(const QString &fileName, int defaultId) -{ - LandscapeItem landItem; - landItem.zoneRegionObject = new ZoneRegionObject(); - landItem.zoneRegionObject->load(fileName.toStdString()); - - if (!checkOverlaps(landItem.zoneRegionObject->ligoZoneRegion())) - { - delete landItem.zoneRegionObject; - return -1; - } - int id = defaultId; - if (id == -1) - id = NewLandId++; -// landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); -// landItem.builderZoneRegion->init(this); - - m_landscapeSceneBase->addZoneRegion(landItem.zoneRegionObject->ligoZoneRegion()); -// landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); - m_landscapeMap.insert(id, landItem); - - calcMask(); - return id; -} - -void ZoneBuilderBase::deleteZoneRegion(int id) -{ - if (m_landscapeMap.contains(id)) - { - m_landscapeSceneBase->delZoneRegion(m_landscapeMap.value(id).zoneRegionObject->ligoZoneRegion()); - delete m_landscapeMap.value(id).zoneRegionObject; -// delete m_landscapeMap.value(id).builderZoneRegion; - m_landscapeMap.remove(id); - calcMask(); - } - else - nlwarning("Landscape (id %i) not found", id); -} - -int ZoneBuilderBase::countZoneRegion() const -{ - return m_landscapeMap.size(); -} - -ZoneRegionObject *ZoneBuilderBase::zoneRegion(int id) const -{ - return m_landscapeMap.value(id).zoneRegionObject; -} - -bool ZoneBuilderBase::initZoneBank (const QString &pathName) -{ - QDir *dir = new QDir(pathName); - QStringList filters; - filters << "*.ligozone"; - - // Find all ligozone files in dir - QStringList listFiles = dir->entryList(filters, QDir::Files); - - std::string error; - Q_FOREACH(QString file, listFiles) - { - //nlinfo(file.toStdString().c_str()); - if (!m_zoneBank.addElement((pathName + file).toStdString(), error)) - QMessageBox::critical(0, QObject::tr("Landscape editor"), QString(error.c_str()), QMessageBox::Ok); - } - delete dir; - return true; -} - -PixmapDatabase *ZoneBuilderBase::pixmapDatabase() const -{ - return m_pixmapDatabase; -} - -QString ZoneBuilderBase::dataPath() const -{ - return m_lastPathName; -} - -void ZoneBuilderBase::calcMask() -{ - m_minY = m_minX = 1000000; - m_maxY = m_maxX = -1000000; - - if (m_landscapeMap.size() == 0) - return; - - QMapIterator i(m_landscapeMap); - while (i.hasNext()) - { - i.next(); - const NLLIGO::CZoneRegion ®ion = i.value().zoneRegionObject->ligoZoneRegion(); - - if (m_minX > region.getMinX()) - m_minX = region.getMinX(); - if (m_minY > region.getMinY()) - m_minY = region.getMinY(); - if (m_maxX < region.getMaxX()) - m_maxX = region.getMaxX(); - if (m_maxY < region.getMaxY()) - m_maxY = region.getMaxY(); - } -} - -bool ZoneBuilderBase::checkOverlaps(const NLLIGO::CZoneRegion &newZoneRegion) -{ - QMapIterator it(m_landscapeMap); - while (it.hasNext()) - { - it.next(); - const NLLIGO::CZoneRegion &zoneRegion = it.value().zoneRegionObject->ligoZoneRegion(); - for (sint32 y = zoneRegion.getMinY(); y <= zoneRegion.getMaxY(); ++y) - for (sint32 x = zoneRegion.getMinX(); x <= zoneRegion.getMaxX(); ++x) - { - const std::string &refZoneName = zoneRegion.getName(x, y); - if (refZoneName != STRING_UNUSED) - { - const std::string &zoneName = newZoneRegion.getName(x, y); - if ((zoneName != STRING_UNUSED) && (zoneName != STRING_OUT_OF_BOUND)) - return false; - } - } - } - return true; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "builder_zone_base.h" +#include "landscape_scene_base.h" +#include "zone_region_editor.h" +#include "pixmap_database.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace LandscapeEditor +{ +int NewLandId = 0; + +ZoneBuilderBase::ZoneBuilderBase(LandscapeSceneBase *landscapeScene) + : m_pixmapDatabase(0), + m_landscapeSceneBase(landscapeScene) +{ + nlassert(m_landscapeSceneBase); + m_pixmapDatabase = new PixmapDatabase(); + m_lastPathName = ""; +} + +ZoneBuilderBase::~ZoneBuilderBase() +{ + delete m_pixmapDatabase; +} + +bool ZoneBuilderBase::init(const QString &pathName, bool displayProgress) +{ + if (pathName.isEmpty()) + return false; + if (pathName != m_lastPathName) + { + m_lastPathName = pathName; + QString zoneBankPath = pathName; + zoneBankPath += "/zoneligos/"; + + // Init the ZoneBank + m_zoneBank.reset(); + if (!initZoneBank (zoneBankPath)) + { + m_zoneBank.reset(); + return false; + } + // Construct the DataBase from the ZoneBank + QString zoneBitmapPath = pathName; + zoneBitmapPath += "/zonebitmaps/"; + m_pixmapDatabase->reset(); + if (!m_pixmapDatabase->loadPixmaps(zoneBitmapPath, m_zoneBank, displayProgress)) + { + m_zoneBank.reset(); + return false; + } + } + return true; +} + +int ZoneBuilderBase::loadZoneRegion(const QString &fileName, int defaultId) +{ + LandscapeItem landItem; + landItem.zoneRegionObject = new ZoneRegionObject(); + landItem.zoneRegionObject->load(fileName.toStdString()); + + if (!checkOverlaps(landItem.zoneRegionObject->ligoZoneRegion())) + { + delete landItem.zoneRegionObject; + return -1; + } + int id = defaultId; + if (id == -1) + id = NewLandId++; +// landItem.builderZoneRegion = new BuilderZoneRegion(LandCounter); +// landItem.builderZoneRegion->init(this); + + m_landscapeSceneBase->addZoneRegion(landItem.zoneRegionObject->ligoZoneRegion()); +// landItem.rectItem = m_landscapeScene->createLayerBlackout(landItem.zoneRegionObject->ligoZoneRegion()); + m_landscapeMap.insert(id, landItem); + + calcMask(); + return id; +} + +void ZoneBuilderBase::deleteZoneRegion(int id) +{ + if (m_landscapeMap.contains(id)) + { + m_landscapeSceneBase->delZoneRegion(m_landscapeMap.value(id).zoneRegionObject->ligoZoneRegion()); + delete m_landscapeMap.value(id).zoneRegionObject; +// delete m_landscapeMap.value(id).builderZoneRegion; + m_landscapeMap.remove(id); + calcMask(); + } + else + nlwarning("Landscape (id %i) not found", id); +} + +int ZoneBuilderBase::countZoneRegion() const +{ + return m_landscapeMap.size(); +} + +ZoneRegionObject *ZoneBuilderBase::zoneRegion(int id) const +{ + return m_landscapeMap.value(id).zoneRegionObject; +} + +bool ZoneBuilderBase::initZoneBank (const QString &pathName) +{ + QDir *dir = new QDir(pathName); + QStringList filters; + filters << "*.ligozone"; + + // Find all ligozone files in dir + QStringList listFiles = dir->entryList(filters, QDir::Files); + + std::string error; + Q_FOREACH(QString file, listFiles) + { + //nlinfo(file.toStdString().c_str()); + if (!m_zoneBank.addElement((pathName + file).toStdString(), error)) + QMessageBox::critical(0, QObject::tr("Landscape editor"), QString(error.c_str()), QMessageBox::Ok); + } + delete dir; + return true; +} + +PixmapDatabase *ZoneBuilderBase::pixmapDatabase() const +{ + return m_pixmapDatabase; +} + +QString ZoneBuilderBase::dataPath() const +{ + return m_lastPathName; +} + +void ZoneBuilderBase::calcMask() +{ + m_minY = m_minX = 1000000; + m_maxY = m_maxX = -1000000; + + if (m_landscapeMap.size() == 0) + return; + + QMapIterator i(m_landscapeMap); + while (i.hasNext()) + { + i.next(); + const NLLIGO::CZoneRegion ®ion = i.value().zoneRegionObject->ligoZoneRegion(); + + if (m_minX > region.getMinX()) + m_minX = region.getMinX(); + if (m_minY > region.getMinY()) + m_minY = region.getMinY(); + if (m_maxX < region.getMaxX()) + m_maxX = region.getMaxX(); + if (m_maxY < region.getMaxY()) + m_maxY = region.getMaxY(); + } +} + +bool ZoneBuilderBase::checkOverlaps(const NLLIGO::CZoneRegion &newZoneRegion) +{ + QMapIterator it(m_landscapeMap); + while (it.hasNext()) + { + it.next(); + const NLLIGO::CZoneRegion &zoneRegion = it.value().zoneRegionObject->ligoZoneRegion(); + for (sint32 y = zoneRegion.getMinY(); y <= zoneRegion.getMaxY(); ++y) + for (sint32 x = zoneRegion.getMinX(); x <= zoneRegion.getMaxX(); ++x) + { + const std::string &refZoneName = zoneRegion.getName(x, y); + if (refZoneName != STRING_UNUSED) + { + const std::string &zoneName = newZoneRegion.getName(x, y); + if ((zoneName != STRING_UNUSED) && (zoneName != STRING_OUT_OF_BOUND)) + return false; + } + } + } + return true; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp index 36c70d4c7..45966ea94 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.cpp @@ -1,2143 +1,2143 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "builder_zone_region.h" -#include "builder_zone.h" -#include "zone_region_editor.h" - -// NeL includes -#include - -// Qt includes - -namespace LandscapeEditor -{ - -BuilderZoneRegion::BuilderZoneRegion(uint regionId) - : m_regionId(regionId), - m_zoneBuilder(0), - m_firstInit(false) -{ -} - -bool BuilderZoneRegion::init(ZoneBuilder *zoneBuilder) -{ - if (m_firstInit) - return true; - - m_zoneBuilder = zoneBuilder; - - uint32 j, k; - SMatNode mn; - std::vector AllValues; - - // Build the material tree - m_zoneBuilder->getZoneBank().getCategoryValues("material", AllValues); - for (uint32 i = 0; i < AllValues.size(); ++i) - { - mn.Name = AllValues[i]; - m_matTree.push_back(mn); - } - - // Link between materials - AllValues.clear (); - m_zoneBuilder->getZoneBank().getCategoryValues("transname", AllValues); - for (uint32 i = 0; i < AllValues.size(); ++i) - { - // Get the 2 materials linked together - std::string matAstr, matBstr; - for (j = 0; j < AllValues[i].size(); ++j) - { - if (AllValues[i][j] == '-') - break; - else - matAstr += AllValues[i][j]; - } - ++j; - for (; j < AllValues[i].size(); ++j) - matBstr += AllValues[i][j]; - - // Find matA - for (j = 0; j < m_matTree.size(); ++j) - if (m_matTree[j].Name == matAstr) - break; - - if (j < m_matTree.size()) - { - // Find matB - for (k = 0; k < m_matTree.size(); ++k) - if (m_matTree[k].Name == matBstr) - break; - - if (k < m_matTree.size()) - { - // Add a ref to matB in node matA - m_matTree[j].Arcs.push_back(k); - - // Add a ref to matA in node matB - m_matTree[k].Arcs.push_back(j); - } - } - } - - m_firstInit = true; - return true; -} - -class ToUpdate -{ - struct SElement - { - sint32 x, y; - - // Material put into the cell to update - std::string matPut; - - BuilderZoneRegion *builderZoneRegion; - }; - - std::vector m_elements; - -public: - - void add(BuilderZoneRegion *builderZoneRegion, sint32 x, sint32 y, const std::string &matName) - { - bool bFound = false; - for (uint32 m = 0; m < m_elements.size(); ++m) - if ((m_elements[m].x == x) && (m_elements[m].y == y)) - { - bFound = true; - break; - } - if (!bFound) - { - SElement newElement; - newElement.x = x; - newElement.y = y; - newElement.matPut = matName; - newElement.builderZoneRegion = builderZoneRegion; - m_elements.push_back (newElement); - } - } - - void del(sint32 x, sint32 y) - { - bool bFound = false; - uint32 m; - for (m = 0; m < m_elements.size(); ++m) - if ((m_elements[m].x == x) && (m_elements[m].y == y)) - { - bFound = true; - break; - } - if (bFound) - { - for (; m < m_elements.size() - 1; ++m) - m_elements[m] = m_elements[m + 1]; - m_elements.resize (m_elements.size() - 1); - } - } - - uint32 size() - { - return m_elements.size(); - } - - sint32 getX(uint32 m) - { - return m_elements[m].x; - } - - sint32 getY(uint32 m) - { - return m_elements[m].y; - } - - BuilderZoneRegion *getBuilderZoneRegion(uint32 m) - { - return m_elements[m].builderZoneRegion; - } - - const std::string &getMat (uint32 m) - { - return m_elements[m].matPut; - } -}; - -void BuilderZoneRegion::add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) -{ - sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); - sint32 i, j; - NLLIGO::SPiece sMask, sPosX, sPosY; - ToUpdate tUpdate; // Transition to update - - if (!m_zoneBuilder->getZoneMask (x,y)) - return; - - if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, rot, flip, zoneBankElement); - return; - } - - // Create the mask in the good rotation and flip - sMask.Tab.resize(sizeX * sizeY); - sPosX.Tab.resize(sizeX * sizeY); - sPosY.Tab.resize(sizeX * sizeY); - - for(j = 0; j < sizeY; ++j) - for(i = 0; i < sizeX; ++i) - { - sPosX.Tab[i + j * sizeX] = (uint8)i; - sPosY.Tab[i + j * sizeX] = (uint8)j; - sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip(rot, flip); - sPosX.rotFlip(rot, flip); - sPosY.rotFlip(rot, flip); - - // Test if the pieces can be put (due to mask) - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i + j * sMask.w]) - { - if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) - return; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i + j * sMask.w]) - { - del(x + i, y + j, true, &tUpdate); - } - - // Delete all around all material that are not from the same as us - const std::string &curMat = zoneBankElement->getCategory("material"); - - if (curMat != STRING_NO_CAT_TYPE) - { - // This element is a valid material - // Place the piece - const std::string &eltName = zoneBankElement->getName(); - placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); - - // Put all transitions between different materials - putTransitions (x, y, sMask, curMat, &tUpdate); - placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); - } -} - -void BuilderZoneRegion::invertCutEdge(sint32 x, sint32 y, uint8 cePos) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || - (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) - return; - - NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); - if (zoneBankElement == NULL) - return; - if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) - return; - - - ZonePosition zonePos(x, y, m_regionId); - LigoData dataZone; - - m_zoneBuilder->ligoData(dataZone, zonePos); - if (dataZone.sharingCutEdges[cePos] != 3 - dataZone.sharingCutEdges[cePos]) - { - dataZone.sharingCutEdges[cePos] = 3 - dataZone.sharingCutEdges[cePos]; - - m_zoneBuilder->actionLigoTile(dataZone, zonePos); - } - updateTrans(x, y); - - // If the transition number is not the same propagate the change - // Propagate where the edge is cut (1/3 or 2/3) and update the transition - if (cePos == 2) - if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[2]) - { - if (x > zoneRegion.getMinX ()) - { - // [x-1][y].right = [x][y].left - // _Zones[(x-1-zoneRegion->getMinX ())+(y-zoneRegion->getMinY ())*stride].SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; - ZonePosition zonePosTemp(x - 1, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.sharingCutEdges[3] != dataZone.sharingCutEdges[2]) - { - dataZoneTemp.sharingCutEdges[3] = dataZone.sharingCutEdges[2]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } - } - updateTrans (x - 1, y); - } - if (cePos == 3) - if (dataZone.sharingMatNames[1] != dataZone.sharingMatNames[3]) - { - if (x < zoneRegion.getMaxX ()) - { - // [x+1][y].left = [x][y].right - ZonePosition zonePosTemp(x + 1, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.sharingCutEdges[2] != dataZone.sharingCutEdges[3]) - { - dataZoneTemp.sharingCutEdges[2] = dataZone.sharingCutEdges[3]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } - } - updateTrans (x + 1, y); - } - if (cePos == 1) - if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[1]) - { - if (y > zoneRegion.getMinY ()) - { - // [x][y-1].up = [x][y].down - ZonePosition zonePosTemp(x, y - 1, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.sharingCutEdges[0] != dataZone.sharingCutEdges[1]) - { - dataZoneTemp.sharingCutEdges[0] = dataZone.sharingCutEdges[1]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } - } - updateTrans (x, y-1); - } - if (cePos == 0) - if (dataZone.sharingMatNames[2] != dataZone.sharingMatNames[3]) - { - if (y < zoneRegion.getMaxY ()) - { - // [x][y+1].down = [x][y].up - ZonePosition zonePosTemp(x, y + 1, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.sharingCutEdges[1] != dataZone.sharingCutEdges[0]) - { - dataZoneTemp.sharingCutEdges[1] = dataZone.sharingCutEdges[0]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } - } - updateTrans (x, y + 1); - } -} - -void BuilderZoneRegion::cycleTransition(sint32 x, sint32 y) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || - (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) - return; - - NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x, y)); - if (zoneBankElement == NULL) - return; - if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) - return; - - // \todo trap -> choose the good transition in function of the transition under the current location - // Choose the next possible transition if not the same as the first one - // Choose among all transition of the same number - - updateTrans (x, y); -} - -bool BuilderZoneRegion::addNotPropagate (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return false; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); - sint32 i, j; - NLLIGO::SPiece sMask, sPosX, sPosY; - ToUpdate tUpdate; // Transition to update - - if (!m_zoneBuilder->getZoneMask (x, y)) - return false; - - if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, rot, flip, zoneBankElement); - return true; - } - - // Create the mask in the good rotation and flip - sMask.Tab.resize (sizeX * sizeY); - sPosX.Tab.resize (sizeX * sizeY); - sPosY.Tab.resize (sizeX * sizeY); - - for (j = 0; j < sizeY; ++j) - for (i = 0; i < sizeX; ++i) - { - sPosX.Tab[i + j * sizeX] = (uint8)i; - sPosY.Tab[i + j * sizeX] = (uint8)j; - sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip (rot, flip); - sPosX.rotFlip (rot, flip); - sPosY.rotFlip (rot, flip); - - // Test if the pieces can be put (due to mask) - sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) - return false; - if (((x + i) < zoneRegion.getMinX ()) || ((x + i) > zoneRegion.getMaxX ()) || - ((y + j) < zoneRegion.getMinY ()) || ((y + j) > zoneRegion.getMaxY ())) - return false; - NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + j)); - if (zoneBankElementUnder == NULL) - return false; - if (zoneBankElementUnder->getCategory("material") != zoneBankElement->getCategory("material")) - return false; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i + j * sMask.w]) - { - del(x + i, y + j, true, &tUpdate); - } - - const std::string &curMat = zoneBankElement->getCategory("material"); - - if (curMat != STRING_NO_CAT_TYPE) - { - // This element is a valid material - // Place the piece - const std::string &eltName = zoneBankElement->getName(); - placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); - } - - return true; -} - -void BuilderZoneRegion::addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); - sint32 i, j; - NLLIGO::SPiece sMask, sPosX, sPosY; - ToUpdate tUpdate; // Transition to update - - if (!m_zoneBuilder->getZoneMask (x, y)) - return; - - /* - if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, nRot, nFlip, pElt); - return; - }*/ - - // Create the mask in the good rotation and flip - sMask.Tab.resize (sizeX * sizeY); - sPosX.Tab.resize (sizeX * sizeY); - sPosY.Tab.resize (sizeX * sizeY); - - for (j = 0; j < sizeY; ++j) - for (i = 0; i < sizeX; ++i) - { - sPosX.Tab[i + j * sizeX] = (uint8)i; - sPosY.Tab[i + j * sizeX] = (uint8)j; - sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip (rot, flip); - sPosX.rotFlip (rot, flip); - sPosY.rotFlip (rot, flip); - - // Test if the pieces can be put (due to mask) - // All space under the mask must be empty - sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (m_zoneBuilder->getZoneMask(x+i, y+j) == false) - return; - if (((x+i) < zoneRegion.getMinX ()) || ((x+i) > zoneRegion.getMaxX ()) || - ((y+j) < zoneRegion.getMinY ()) || ((y+j) > zoneRegion.getMaxY ())) - return; - NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + i)); - if (zoneBankElementUnder != NULL) - return; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - del(x+i, y+j, true, &tUpdate); - } - - const std::string &curMat = zoneBankElement->getCategory ("material"); - const bool transition = zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE; - - if (curMat != STRING_NO_CAT_TYPE || transition) - { - // This element is a valid material - // Place the piece - const std::string &eltName = zoneBankElement->getName(); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i + j * sMask.w]) - { - set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName, transition); - setRot(x + i, y + j, rot); - setFlip(x + i, y + j, flip); - } - } -} - -uint8 TransToEdge[72][4] = -{ - { 0, 0, 1, 1 }, // TransNum = 0, Flip = 0, Rot = 0 - { 2, 2, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 1 - { 0, 0, 2, 2 }, // TransNum = 0, Flip = 0, Rot = 2 - { 1, 1, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 3 - { 0, 0, 1, 1 }, // TransNum = 0, Flip = 1, Rot = 0 - { 2, 2, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 1 - { 0, 0, 2, 2 }, // TransNum = 0, Flip = 1, Rot = 2 - { 1, 1, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 3 - - { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 0 - { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 1 - { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 2 - { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 3 - { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 0 - { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 1 - { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 2 - { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 3 - - { 0, 0, 2, 2 }, // TransNum = 2, Flip = 0, Rot = 0 - { 1, 1, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 1 - { 0, 0, 1, 1 }, // TransNum = 2, Flip = 0, Rot = 2 - { 2, 2, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 3 - { 0, 0, 2, 2 }, // TransNum = 2, Flip = 1, Rot = 0 - { 1, 1, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 1 - { 0, 0, 1, 1 }, // TransNum = 2, Flip = 1, Rot = 2 - { 2, 2, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 3 - - { 0, 1, 1, 0 }, // TransNum = 3, Flip = 0, Rot = 0 - { 0, 2, 0, 1 }, // TransNum = 3, Flip = 0, Rot = 1 - { 2, 0, 0, 2 }, // TransNum = 3, Flip = 0, Rot = 2 - { 1, 0, 2, 0 }, // TransNum = 3, Flip = 0, Rot = 3 - { 0, 2, 0, 1 }, // TransNum = 3, Flip = 1, Rot = 0 - { 2, 0, 0, 2 }, // TransNum = 3, Flip = 1, Rot = 1 - { 1, 0, 2, 0 }, // TransNum = 3, Flip = 1, Rot = 2 - { 0, 1, 1, 0 }, // TransNum = 3, Flip = 1, Rot = 3 - - { 0, 2, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 0 - { 0, 2, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 1 - { 1, 0, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 2 - { 1, 0, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 3 - { 0, 1, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 0 - { 2, 0, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 1 - { 2, 0, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 2 - { 0, 1, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 3 - - { 0, 2, 2, 0 }, // TransNum = 5, Flip = 0, Rot = 0 - { 0, 1, 0, 2 }, // TransNum = 5, Flip = 0, Rot = 1 - { 1, 0, 0, 1 }, // TransNum = 5, Flip = 0, Rot = 2 - { 2, 0, 1, 0 }, // TransNum = 5, Flip = 0, Rot = 3 - { 0, 1, 0, 2 }, // TransNum = 5, Flip = 1, Rot = 0 - { 1, 0, 0, 1 }, // TransNum = 5, Flip = 1, Rot = 1 - { 2, 0, 1, 0 }, // TransNum = 5, Flip = 1, Rot = 2 - { 0, 2, 2, 0 }, // TransNum = 5, Flip = 1, Rot = 3 - - { 0, 1, 1, 0 }, // TransNum = 6, Flip = 0, Rot = 0 - { 0, 2, 0, 1 }, // TransNum = 6, Flip = 0, Rot = 1 - { 2, 0, 0, 2 }, // TransNum = 6, Flip = 0, Rot = 2 - { 1, 0, 2, 0 }, // TransNum = 6, Flip = 0, Rot = 3 - { 0, 2, 0, 1 }, // TransNum = 6, Flip = 1, Rot = 0 - { 2, 0, 0, 2 }, // TransNum = 6, Flip = 1, Rot = 1 - { 1, 0, 2, 0 }, // TransNum = 6, Flip = 1, Rot = 2 - { 0, 1, 1, 0 }, // TransNum = 6, Flip = 1, Rot = 3 - - { 0, 2, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 0 - { 0, 2, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 1 - { 1, 0, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 2 - { 1, 0, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 3 - { 0, 1, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 0 - { 2, 0, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 1 - { 2, 0, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 2 - { 0, 1, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 3 - - { 0, 2, 2, 0 }, // TransNum = 8, Flip = 0, Rot = 0 - { 0, 1, 0, 2 }, // TransNum = 8, Flip = 0, Rot = 1 - { 1, 0, 0, 1 }, // TransNum = 8, Flip = 0, Rot = 2 - { 2, 0, 1, 0 }, // TransNum = 8, Flip = 0, Rot = 3 - { 0, 1, 0, 2 }, // TransNum = 8, Flip = 1, Rot = 0 - { 1, 0, 0, 1 }, // TransNum = 8, Flip = 1, Rot = 1 - { 2, 0, 1, 0 }, // TransNum = 8, Flip = 1, Rot = 2 - { 0, 2, 2, 0 }, // TransNum = 8, Flip = 1, Rot = 3 -}; - -void BuilderZoneRegion::addTransition (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - uint32 i; - // Check that we write in an already defined place - if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || - (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) - return; - - // Check size - if ((zoneBankElement->getSizeX() != 1) || (zoneBankElement->getSizeY() != 1)) - return; - - // Check that an element already exist at position we want put the transition - NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); - if (zoneBankElementUnder == NULL) - return; - - // And check that this element is also a transition and the same transition - if (zoneBankElementUnder->getCategory ("transname") == STRING_NO_CAT_TYPE) - return; - if (zoneBankElementUnder->getCategory ("transname") != zoneBankElement->getCategory("transname")) - return; - - std::string underType = zoneBankElementUnder->getCategory("transtype"); - std::string overType = zoneBankElement->getCategory("transtype"); - std::string underNum = zoneBankElementUnder->getCategory("transnum"); - std::string overNum = zoneBankElement ->getCategory("transnum"); - - ZonePosition zonePosTemp(x, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - LigoData dataZoneOriginal = dataZoneTemp; - - bool bMustPropagate = false; - // Same type of transition ? - if (zoneBankElementUnder->getCategory("transtype") != zoneBankElement->getCategory("transtype")) - { - // No so random the cutEdges - for (i = 0; i < 4; ++i) - { - uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); - NLMISC::clamp(nCut, (uint8)1, (uint8)2); - - dataZoneTemp.sharingCutEdges[i] = nCut; - } - zoneBankElement = NULL; - bMustPropagate = true; - } - else - { - // Put exactly the transition as given - sint32 transnum = atoi(zoneBankElement->getCategory("transnum").c_str()); - sint32 flip = zoneRegion.getFlip(x, y); - sint32 rot = zoneRegion.getRot(x, y); - sint32 pos1 = -1, pos2 = -1; - - for (i = 0; i < 4; ++i) - { - if ((TransToEdge[transnum * 8 + flip * 4 + rot][i] != 0) && - (TransToEdge[transnum * 8 + flip * 4 + rot][i] != dataZoneTemp.sharingCutEdges[i])) - bMustPropagate = true; - - dataZoneTemp.sharingCutEdges[i] = TransToEdge[transnum * 8 + flip * 4 + rot][i]; - - if ((pos1 != -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) - pos2 = i; - if ((pos1 == -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) - pos1 = i; - } - // Exchange cutedges != 0 one time /2 to permit all positions - if ((transnum == 1) || (transnum == 4) || (transnum == 7)) - if (zoneBankElement->getName() == zoneBankElementUnder->getName()) - { - bMustPropagate = true; - - dataZoneTemp.sharingCutEdges[pos1] = 3 - dataZoneTemp.sharingCutEdges[pos1]; - dataZoneTemp.sharingCutEdges[pos2] = 3 - dataZoneTemp.sharingCutEdges[pos2]; - } - } - if (dataZoneTemp != dataZoneOriginal) - { - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } - updateTrans (x, y, zoneBankElement); - - // If the transition number is not the same propagate the change - if (bMustPropagate) - { - // Propagate where the edge is cut (1/3 or 2/3) and update the transition - if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) - { - if (x > zoneRegion.getMinX ()) - { - // [x-1][y].right = [x][y].left - // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; - ZonePosition zonePosTemp2(x - 1, y, m_regionId); - LigoData dataZoneTemp2; - m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); - if (dataZoneTemp2.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) - { - dataZoneTemp2.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); - } - } - updateTrans (x - 1, y); - } - if (dataZoneTemp.sharingMatNames[1] != dataZoneTemp.sharingMatNames[3]) - { - if (x < zoneRegion.getMaxX ()) - { - // [x+1][y].left = [x][y].right - //_Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; - ZonePosition zonePosTemp2(x + 1, y, m_regionId); - LigoData dataZoneTemp2; - m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); - if (dataZoneTemp2.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) - { - dataZoneTemp2.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); - } - } - updateTrans (x + 1, y); - } - if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) - { - if (y > zoneRegion.getMinY ()) - { - // [x][y-1].up = [x][y].down - //_Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; - ZonePosition zonePosTemp2(x, y - 1, m_regionId); - LigoData dataZoneTemp2; - m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); - if (dataZoneTemp2.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) - { - dataZoneTemp2.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); - } - } - updateTrans (x, y - 1); - } - if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) - { - if (y < zoneRegion.getMaxY ()) - { - // [x][y+1].down = [x][y].up - //_Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; - ZonePosition zonePosTemp2(x, y + 1, m_regionId); - LigoData dataZoneTemp2; - m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); - if (dataZoneTemp2.sharingCutEdges[1] != dataZoneTemp.sharingCutEdges[0]) - { - dataZoneTemp2.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); - } - } - updateTrans (x, y + 1); - } - } -} - -void BuilderZoneRegion::addToUpdateAndCreate(BuilderZoneRegion *builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, - const std::string &newMat, ToUpdate *ptCreate, ToUpdate *ptUpdate) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - sint32 stride = (1 + zoneRegion.getMaxX() - zoneRegion.getMinX()); - - ZonePosition zonePos; - if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion, x, y)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePos); - if (data.sharingMatNames[sharePos] != newMat) - { - data.sharingMatNames[sharePos] = newMat; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePos); - } - builderZoneRegion->del(x, y, true, ptUpdate); - ptCreate->add(builderZoneRegion, x, y, newMat); - } -} - -void BuilderZoneRegion::putTransitions (sint32 inX, sint32 inY, const NLLIGO::SPiece &mask, const std::string &matName, - ToUpdate *ptUpdate) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - ToUpdate tCreate; // Transition to create - - sint32 i, j, k, l, m; - sint32 x = inX, y = inY; - for (j = 0; j < mask.h; ++j) - for (i = 0; i < mask.w; ++i) - if (mask.Tab[i + j * mask.w]) - { - for (k = -1; k <= 1; ++k) - for (l = -1; l <= 1; ++l) - { - BuilderZoneRegion *builderZoneRegion2 = this; - ZonePosition zonePos; - if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion2, inX + i + l, inY + j + k)) - tCreate.add(builderZoneRegion2, inX + i + l, inY + j + k, matName); - } - } - - // Check coherency of the transition to update - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - BuilderZoneRegion *builderZoneRegion2 = tCreate.getBuilderZoneRegion(m); - x = tCreate.getX(m); - y = tCreate.getY(m); - std::string putMat = tCreate.getMat(m); - - //if ((x < pBZR->getMinX ())||(x > pBZR->getMaxX ())||(y < pBZR->getMinY ())||(y > pBZR->getMaxY ())) - // continue; - - ZonePosition zoneTemp(x, y, builderZoneRegion2->getRegionId()); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - - if (!((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[1])&& - (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2])&& - (dataZoneTemp.sharingMatNames[2] == dataZoneTemp.sharingMatNames[3]))) - builderZoneRegion2->del(x, y, true, ptUpdate); - - // Check to see material can be posed - uint corner; - for (corner = 0; corner < 4; corner++) - { - std::string newMat = getNextMatInTree (putMat, dataZoneTemp.sharingMatNames[corner]); - - // Can't be posed ? - if (newMat == STRING_UNUSED) - break; - } - if ( (corner < 4) && (m != 0) ) - { - // The material can't be paused - for (int t = 0; t < 4; ++t) - dataZoneTemp.sharingMatNames[t] = STRING_UNUSED; - - // Don't propagate any more - } - else - { - // Expand material for the 1st quarter - std::string newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[0]); - if (newMat != dataZoneTemp.sharingMatNames[0]) - { - // Update the quarter - if (dataZoneTemp.sharingMatNames[0] != newMat) - { - dataZoneTemp.sharingMatNames[0] = newMat; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - - addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y - 1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 2, x, y - 1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 2nd quarter - newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[1]); - if (newMat != dataZoneTemp.sharingMatNames[1]) - { - // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.sharingMatNames[1] != newMat) - { - dataZoneTemp.sharingMatNames[1] = newMat; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - - addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y - 1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 3, x, y - 1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 3rd quarter - newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[2]); - if (newMat != dataZoneTemp.sharingMatNames[2]) - { - // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.sharingMatNames[2] != newMat) - { - dataZoneTemp.sharingMatNames[2] = newMat; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - - addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y + 1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 0, x, y + 1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 4th quarter - newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[3]); - if (newMat != dataZoneTemp.sharingMatNames[3]) - { - // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.sharingMatNames[3] != newMat) - { - dataZoneTemp.sharingMatNames[3] = newMat; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - - addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y + 1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate(builderZoneRegion2, 1, x, y + 1, newMat, &tCreate, ptUpdate); - } - } - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - - // Delete transitions that are inside the mask - for (j = 0; j < mask.h; ++j) - for (i = 0; i < mask.w; ++i) - if (mask.Tab[i + j * mask.w]) - { - tCreate.del(inX + i, inY + j); - } - - // For all transition to update choose the cut edge - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - ZoneRegionObject *zoneRegionObj2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId()); - if (zoneRegionObj2 == 0) - continue; - - const NLLIGO::CZoneRegion &zoneRegion2 = zoneRegionObj2->ligoZoneRegion(); - x = tCreate.getX(m); - y = tCreate.getY(m); - - if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || - (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) - continue; - - ZonePosition zoneTemp(x, y, tCreate.getBuilderZoneRegion(m)->getRegionId()); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - LigoData dataZoneTempOriginal = dataZoneTemp; - - for (i = 0; i < 4; ++i) - { - uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); - NLMISC::clamp(nCut, (uint8)1, (uint8)2); - dataZoneTemp.sharingCutEdges[i] = nCut; - } - - // Add modification landscape - if (dataZoneTempOriginal != dataZoneTemp) - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - - // Propagate - if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) - { - // [x-1][y].right = [x][y].left - BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); - ZonePosition zonePosU; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x - 1, y)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) - { - data.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - ptUpdate->add(builderZoneRegion3, x - 1, y, ""); - } - } - else - { - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - if (dataZoneTemp.sharingCutEdges[2] != 0) - { - dataZoneTemp.sharingCutEdges[2] = 0; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - } - - if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) - { - // [x][y-1].up = [x][y].down - BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); - ZonePosition zonePosU; - if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y - 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) - { - data.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - ptUpdate->add (builderZoneRegion3, x, y - 1, ""); - } - } - else - { - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - if (dataZoneTemp.sharingCutEdges[1] != 0) - { - dataZoneTemp.sharingCutEdges[1] = 0; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - } - - if (dataZoneTemp.sharingMatNames[3] != dataZoneTemp.sharingMatNames[1]) - { - // [x+1][y].left = [x][y].right - BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); - ZonePosition zonePosU; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x + 1, y)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) - { - data.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - ptUpdate->add(builderZoneRegion3, x + 1, y, ""); - } - } - else - { - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - if (dataZoneTemp.sharingCutEdges[3] != 0) - { - dataZoneTemp.sharingCutEdges[3] = 0; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - } - - if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) - { - // [x][y+1].down = [x][y].up - BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); - ZonePosition zonePosU; - if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y+1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]) - { - data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - ptUpdate->add (builderZoneRegion3, x, y + 1, ""); - } - } - else - { - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - if (dataZoneTemp.sharingCutEdges[0] = 0) - { - dataZoneTemp.sharingCutEdges[0] = 0; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); - } - } - } - - // Delete in tUpdate each element in common with tCreate - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - x = tCreate.getX(m); - y = tCreate.getY(m); - ptUpdate->del (x,y); - } - - // Finally update all transition - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); - x = tCreate.getX(m); - y = tCreate.getY(m); - - if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && - (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) - tCreate.getBuilderZoneRegion(m)->updateTrans(x, y); - } - - // WARNING: TODO: check this for - for (m = 0; m < (sint32)ptUpdate->size(); ++m) - { - const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(ptUpdate->getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); - x = ptUpdate->getX(m); - y = ptUpdate->getY(m); - if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && - (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) - ptUpdate->getBuilderZoneRegion(m)->updateTrans(x, y); - } - - // Cross material - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); - x = tCreate.getX(m); - y = tCreate.getY(m); - - - ZonePosition zoneTemp(x, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); - - std::set matNameSet; - for (i = 0; i < 4; ++i) - matNameSet.insert(dataZoneTemp.sharingMatNames[i]); - - if (((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[3]) && - (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2]) && - (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1])) - || (matNameSet.size()>2)) - { - NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); - zoneBank.resetSelection(); - zoneBank.addOrSwitch("material", tCreate.getMat(m)); - zoneBank.addAndSwitch("size", "1x1"); - std::vector vElts; - zoneBank.getSelection(vElts); - if (vElts.size() == 0) - return; - sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); - NLMISC::clamp(nRan, (sint32)0, (sint32)(vElts.size() - 1)); - NLLIGO::CZoneBankElement *zoneBankElement = vElts[nRan]; - nRan = (uint32)(NLMISC::frand (1.0) * 4); - NLMISC::clamp(nRan, (sint32)0, (sint32)3); - uint8 rot = (uint8)nRan; - nRan = (uint32)(NLMISC::frand (1.0) * 2); - NLMISC::clamp (nRan, (sint32)0, (sint32)1); - uint8 flip = (uint8)nRan; - - tCreate.getBuilderZoneRegion(m)->add(x, y, rot, flip, zoneBankElement); - } - } -} - -struct STrans -{ - uint8 Num; - uint8 Rot; - uint8 Flip; -}; - -STrans TranConvTable[128] = -{ - { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 1 UNUSED - - { 6,0,0 }, // Quart = 1, CutEdge = 0, Np = 0 - { 6,3,1 }, // Quart = 1, CutEdge = 0, Np = 1 - { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 0 - { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 1 - { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 0 - { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 1 - { 8,0,0 }, // Quart = 1, CutEdge = 3, Np = 0 - { 8,3,1 }, // Quart = 1, CutEdge = 3, Np = 1 - - { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 0 - { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 1 - { 6,0,1 }, // Quart = 2, CutEdge = 1, Np = 0 - { 6,1,0 }, // Quart = 2, CutEdge = 1, Np = 1 - { 8,1,0 }, // Quart = 2, CutEdge = 2, Np = 0 - { 8,0,1 }, // Quart = 2, CutEdge = 2, Np = 1 - { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 0 - { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 3, CutEdge = 0, Np = 0 - { 0,0,1 }, // Quart = 3, CutEdge = 0, Np = 1 - { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 0 - { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 1 - { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 0 - { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 1 - { 2,0,0 }, // Quart = 3, CutEdge = 3, Np = 0 - { 2,0,1 }, // Quart = 3, CutEdge = 3, Np = 1 - - { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 0 - { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 1 - { 8,3,0 }, // Quart = 4, CutEdge = 1, Np = 0 - { 8,2,1 }, // Quart = 4, CutEdge = 1, Np = 1 - { 6,3,0 }, // Quart = 4, CutEdge = 2, Np = 0 - { 6,2,1 }, // Quart = 4, CutEdge = 2, Np = 1 - { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 0 - { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 1 - - { 0,3,0 }, // Quart = 5, CutEdge = 0, Np = 0 - { 0,3,1 }, // Quart = 5, CutEdge = 0, Np = 1 - { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 0 - { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 1 - { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 0 - { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 1 - { 2,3,0 }, // Quart = 5, CutEdge = 3, Np = 0 - { 2,3,1 }, // Quart = 5, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 1 UNUSED - - { 5,2,0 }, // Quart = 7, CutEdge = 0, Np = 0 - { 5,1,1 }, // Quart = 7, CutEdge = 0, Np = 1 - { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 0 - { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 1 - { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 0 - { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 1 - { 3,2,0 }, // Quart = 7, CutEdge = 3, Np = 0 - { 3,1,1 }, // Quart = 7, CutEdge = 3, Np = 1 - - { 8,2,0 }, // Quart = 8, CutEdge = 0, Np = 0 - { 8,1,1 }, // Quart = 8, CutEdge = 0, Np = 1 - { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 0 - { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 1 - { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 0 - { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 1 - { 6,2,0 }, // Quart = 8, CutEdge = 3, Np = 0 - { 6,1,1 }, // Quart = 8, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 1 UNUSED - - { 2,1,0 }, // Quart = 10, CutEdge = 0, Np = 0 - { 2,1,1 }, // Quart = 10, CutEdge = 0, Np = 1 - { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 0 - { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 1 - { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 0 - { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 1 - { 0,1,0 }, // Quart = 10, CutEdge = 3, Np = 0 - { 0,1,1 }, // Quart = 10, CutEdge = 3, Np = 1 - - { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 0 - { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 1 - { 5,3,0 }, // Quart = 11, CutEdge = 1, Np = 0 - { 5,2,1 }, // Quart = 11, CutEdge = 1, Np = 1 - { 3,3,0 }, // Quart = 11, CutEdge = 2, Np = 0 - { 3,2,1 }, // Quart = 11, CutEdge = 2, Np = 1 - { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 0 - { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 1 - - { 2,2,0 }, // Quart = 12, CutEdge = 0, Np = 0 - { 2,2,1 }, // Quart = 12, CutEdge = 0, Np = 1 - { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 0 - { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 1 - { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 0 - { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 1 - { 0,2,0 }, // Quart = 12, CutEdge = 3, Np = 0 - { 0,2,1 }, // Quart = 12, CutEdge = 3, Np = 1 - - { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 0 - { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 1 - { 3,1,0 }, // Quart = 13, CutEdge = 1, Np = 0 - { 3,0,1 }, // Quart = 13, CutEdge = 1, Np = 1 - { 5,1,0 }, // Quart = 13, CutEdge = 2, Np = 0 - { 5,0,1 }, // Quart = 13, CutEdge = 2, Np = 1 - { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 0 - { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 1 - - { 3,0,0 }, // Quart = 14, CutEdge = 0, Np = 0 - { 3,3,1 }, // Quart = 14, CutEdge = 0, Np = 1 - { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 0 - { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 1 - { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 0 - { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 1 - { 5,0,0 }, // Quart = 14, CutEdge = 3, Np = 0 - { 5,3,1 }, // Quart = 14, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 } // Quart = 15, CutEdge = 3, Np = 1 UNUSED -}; - -void BuilderZoneRegion::updateTrans (sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement) -{ - const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); - if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || - (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) - return; - - //if (!_Builder->getZoneMask(x,y)) - // return; - - // Interpret the transition info - x -= zoneRegion.getMinX (); - y -= zoneRegion.getMinY (); - sint32 m; - - // Calculate the number of material around with transition info - std::set matNameSet; - - ZonePosition zonePosTemp(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - LigoData dataZoneTempOriginal = dataZoneTemp; - - for (m = 0; m < 4; ++m) - matNameSet.insert(dataZoneTemp.sharingMatNames[m]); - - if (matNameSet.size() == 1) - { - if (dataZoneTemp.sharingMatNames[0] == STRING_UNUSED) - { - del(x + zoneRegion.getMinX (), y + zoneRegion.getMinY ()); - // set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, STRING_UNUSED, false); - return; - } - else - { - NLLIGO::CZoneBankElement *zoneBankElement2 = m_zoneBuilder->getZoneBank().getElementByZoneName(dataZoneTemp.zoneName); - if ((zoneBankElement != NULL) && (zoneBankElement2 != NULL) && (zoneBankElement2->getCategory("material") == dataZoneTemp.sharingMatNames[0])) - return; - - NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); - zoneBank.resetSelection (); - zoneBank.addOrSwitch ("material", dataZoneTemp.sharingMatNames[0]); - zoneBank.addAndSwitch ("size", "1x1"); - std::vector vElts; - zoneBank.getSelection (vElts); - if (vElts.size() == 0) - return; - sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); - NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); - zoneBankElement = vElts[nRan]; - nRan = (uint32)(NLMISC::frand(1.0) * 4); - NLMISC::clamp (nRan, (sint32)0, (sint32)3); - uint8 rot = (uint8)nRan; - nRan = (uint32)(NLMISC::frand(1.0) * 2); - NLMISC::clamp (nRan, (sint32)0, (sint32)1); - uint8 flip = (uint8)nRan; - - set(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), 0, 0, zoneBankElement->getName(), false); - setRot(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), rot); - setFlip(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), flip); - return; - } - } - - // No 2 materials so the transition system dont work - if (matNameSet.size() != 2) - return; - - std::set::iterator it = matNameSet.begin(); - std::string matA = *it; - ++it; - std::string matB = *it; - - NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); - zoneBank.resetSelection (); - zoneBank.addOrSwitch("transname", matA + "-" + matB); - std::vector selection; - zoneBank.getSelection(selection); - if (selection.size() == 0) - { - std::string matTmp = matA; - matA = matB; - matB = matTmp; - zoneBank.resetSelection (); - zoneBank.addOrSwitch ("transname", matA + "-" + matB); - zoneBank.getSelection (selection); - } - - if (selection.size() == 0) - return; - - // Convert the sharingCutEdges and SharingNames to the num and type of transition - uint8 nQuart = 0; // 0-MatA 1-MatB - for (m = 0; m < 4; ++m) - if (dataZoneTemp.sharingMatNames[m] == matB) - nQuart |= (1 << m); - - if ((nQuart == 0) || (nQuart == 6) || - (nQuart == 9) || (nQuart == 15)) - return; // No transition for those types - - uint8 nCutEdge = 0; - uint8 nPosCorner = 0; - - // If up edge is cut write the cut position in nCutEdge bitfield (1->0, 2->1) - if ((nQuart == 4) || (nQuart == 5) || - (nQuart == 7) || (nQuart == 8) || - (nQuart == 10) || (nQuart == 11)) - { - if (dataZoneTemp.sharingCutEdges[0] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.sharingCutEdges[0] = 0; - } - - // Same for down edge - if ((nQuart == 1) || (nQuart == 2) || - (nQuart == 5) || (nQuart == 10) || - (nQuart == 13) || (nQuart == 14)) - { - if (dataZoneTemp.sharingCutEdges[1] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.sharingCutEdges[1] = 0; - } - - // Same for left edge - if ((nQuart == 1) || (nQuart == 3) || - (nQuart == 4) ||(nQuart == 11) || - (nQuart == 12) || (nQuart == 14)) - { - if (dataZoneTemp.sharingCutEdges[2] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.sharingCutEdges[2] = 0; - } - - // Same for right edge - if ((nQuart == 2) || (nQuart == 3) || - (nQuart == 7) || (nQuart == 8) || - (nQuart == 12) || (nQuart == 13)) - { - if (dataZoneTemp.sharingCutEdges[3] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.sharingCutEdges[3] = 0; - } - - nlassert (nPosCorner == 2); // If not this means that more than 2 edges are cut which is not possible - - STrans Trans, TransTmp1, TransTmp2; - - TransTmp1 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 0]; - TransTmp2 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 1]; - - // Choose one or the two - sint32 nTrans = (sint32)(NLMISC::frand(2.0f)); - NLMISC::clamp(nTrans, (sint32)0, (sint32)1); - if (nTrans == 0) - Trans = TransTmp1; - else - Trans = TransTmp2; - - zoneBank.addAndSwitch ("transnum", NLMISC::toString(Trans.Num)); - zoneBank.getSelection (selection); - - if (selection.size() > 0) - { - if (zoneBankElement != NULL) - { - dataZoneTemp.zoneName = zoneBankElement->getName(); - } - else - { - nTrans = (uint32)(NLMISC::frand (1.0) * selection.size()); - NLMISC::clamp(nTrans, (sint32)0, (sint32)(selection.size() - 1)); - dataZoneTemp.zoneName = selection[nTrans]->getName(); - } - dataZoneTemp.posX = dataZoneTemp.posY = 0; - dataZoneTemp.rot = Trans.Rot; - dataZoneTemp.flip = Trans.Flip; - } - - // Add modification landscape - if (dataZoneTempOriginal != dataZoneTemp) - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); -} - -std::string BuilderZoneRegion::getNextMatInTree (const std::string &matA, const std::string &matB) -{ - const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); - uint32 i, posA = 10000, posB = 10000; - - if (matA == matB) - return matA; - - for (i = 0; i < m_matTree.size(); ++i) - { - if (m_matTree[i].Name == matA) - posA = i; - if (m_matTree[i].Name == matB) - posB = i; - } - if ((posA == 10000) || (posB == 10000)) - return STRING_UNUSED; - - std::vector vTemp; - tryPath (posA, posB, vTemp); - if (vTemp.size() <= 1) - return STRING_UNUSED; - else - return m_matTree[vTemp[1]].Name; -} - -struct SNode -{ - sint32 NodePos, Dist, PrevNodePos; - - SNode() - { - NodePos = Dist = PrevNodePos = -1; - } -}; - -void BuilderZoneRegion::tryPath(uint32 posA, uint32 posB, std::vector &path) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - - // Build the adjascence matrix - std::vector matAdj; - sint32 numNodes = m_matTree.size(); - sint32 i, j, cost; - matAdj.resize(numNodes * numNodes, -1); - for (i = 0; i < numNodes; ++i) - for (j = 0; j < (sint32)m_matTree[i].Arcs.size(); ++j) - matAdj[i + m_matTree[i].Arcs[j] * numNodes] = 1; - - std::vector vNodes; // NodesPos == index - vNodes.resize (numNodes); - for (i = 0; i < numNodes; ++i) - vNodes[i].NodePos = i; - vNodes[posA].Dist = 0; - - std::queue qNodes; - qNodes.push (vNodes[posA]); - - while (qNodes.size() > 0) - { - SNode node = qNodes.front(); - qNodes.pop (); - - for (i = 0; i < numNodes; ++i) - { - cost = matAdj[node.NodePos + i * numNodes]; - if (cost != -1) - { - if ((vNodes[i].Dist == -1) || (vNodes[i].Dist > (cost + node.Dist))) - { - vNodes[i].Dist = cost + node.Dist; - vNodes[i].PrevNodePos = node.NodePos; - qNodes.push(vNodes[i]); - } - } - } - } - - // Get path length - i = posB; - j = 0; - while (i != -1) - { - ++j; - i = vNodes[i].PrevNodePos; - } - - // Write the path in the good order (from posA to posB) - path.resize(j); - i = posB; - while (i != -1) - { - --j; - path[j] = i; - i = vNodes[i].PrevNodePos; - } -} - -void BuilderZoneRegion::del(sint32 x, sint32 y, bool transition, ToUpdate *pUpdate) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - if (!m_zoneBuilder->getZoneMask(x, y)) - return; - - const std::string &nameZone = zoneRegion.getName(x, y); - NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(nameZone); - if (zoneBankElement != NULL) - { - sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); - sint32 posX = zoneRegion.getPosX (x, y), posY = zoneRegion.getPosY (x, y); - uint8 rot = zoneRegion.getRot (x, y); - uint8 flip = zoneRegion.getFlip (x, y); - sint32 i, j; - sint32 deltaX, deltaY; - - if (flip == 0) - { - switch (rot) - { - case 0: - deltaX = -posX; - deltaY = -posY; - break; - case 1: - deltaX = -(sizeY - 1 - posY); - deltaY = -posX; - break; - case 2: - deltaX = -(sizeX - 1 - posX); - deltaY = -(sizeY - 1 - posY); - break; - case 3: - deltaX = -posY; - deltaY = -(sizeX - 1 - posX); - break; - } - } - else - { - switch (rot) - { - case 0: - deltaX = -(sizeX - 1 - posX); - deltaY = -posY; - break; - case 1: - deltaX = -(sizeY - 1 - posY); - deltaY = -(sizeX - 1 - posX); - break; - case 2: - deltaX = -posX; - deltaY = -(sizeY - 1 - posY); - break; - case 3: - deltaX = -posY; - deltaY = -posX; - break; - } - } - - NLLIGO::SPiece mask; - mask.Tab.resize (sizeX * sizeY); - for(i = 0; i < sizeX * sizeY; ++i) - mask.Tab[i] = zoneBankElement->getMask()[i]; - mask.w = sizeX; - mask.h = sizeY; - mask.rotFlip (rot, flip); - - for (j = 0; j < mask.h; ++j) - for (i = 0; i < mask.w; ++i) - if (mask.Tab[i + j * mask.w]) - { - set(x + deltaX + i, y + deltaY + j, 0, 0, STRING_UNUSED, true); - setRot(x + deltaX + i, y + deltaY + j, 0); - setFlip(x + deltaX + i, y + deltaY + j, 0); - if (pUpdate != NULL) - { - pUpdate->add(this, x + deltaX + i, y + deltaY + j, ""); - } - } - if (!transition) - reduceMin (); - } - else - { - if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || - (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) - return; - - ZonePosition zonePosTemp(x, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - LigoData dataZoneTempOriginal = dataZoneTemp; - - dataZoneTemp.zoneName = STRING_UNUSED; - dataZoneTemp.posX = 0; - dataZoneTemp.posY = 0; - - for (uint32 i = 0; i < 4; ++i) - { - dataZoneTemp.sharingMatNames[i] = STRING_UNUSED; - dataZoneTemp.sharingCutEdges[i] = 0; - } - - // Add modification landscape - if (dataZoneTempOriginal != dataZoneTemp) - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - - } -} - -void BuilderZoneRegion::move (sint32 x, sint32 y) -{ - m_zoneBuilder->actionLigoMove(m_regionId, x, y); -} - -uint32 BuilderZoneRegion::countZones () -{ - const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); - sint32 x, y; - - uint32 counter = 0; - - for (y = zoneRegion.getMinY (); y <= zoneRegion.getMaxY (); ++y) - for (x = zoneRegion.getMinX (); x <= zoneRegion.getMaxX (); ++x) - if (zoneRegion.getName (x, y) != STRING_UNUSED) - ++counter; - - return counter; -} - -void BuilderZoneRegion::set(sint32 x, sint32 y, sint32 posX, sint32 posY, - const std::string &zoneName, bool transition) -{ - ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); - if (zoneRegionObj == 0) - return; - - const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); - - // Do we need to resize ? - if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || - (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) - { - sint32 newMinX = (x < zoneRegion.getMinX() ? x: zoneRegion.getMinX()), newMinY = (y < zoneRegion.getMinY() ? y: zoneRegion.getMinY()); - sint32 newMaxX = (x > zoneRegion.getMaxX() ? x: zoneRegion.getMaxX()), newMaxY = (y > zoneRegion.getMaxY() ? y: zoneRegion.getMaxY()); - - resize(newMinX, newMaxX, newMinY, newMaxY); - } - - ZonePosition zonePosTemp(x, y, m_regionId); - LigoData dataZoneTemp; - if (!m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp)) - return; - LigoData dataZoneTempOriginal = dataZoneTemp; - - dataZoneTemp.zoneName = zoneName; - dataZoneTemp.posX = (uint8)posX; - dataZoneTemp.posY = (uint8)posY; - - if (!transition) - { - NLLIGO::CZoneBankElement *zoneBankElem = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneName); - if (zoneBankElem == NULL) - return; - - const std::string &matName = zoneBankElem->getCategory ("material"); - if (matName == STRING_NO_CAT_TYPE) - return; - for (uint32 i = 0; i < 4; ++i) - { - dataZoneTemp.sharingMatNames[i] = matName; - dataZoneTemp.sharingCutEdges[i] = 0; - } - - // Add modification landscape - if (dataZoneTempOriginal != dataZoneTemp) - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - - BuilderZoneRegion *builderZoneRegion = this; - ZonePosition zonePosU; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y - 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingMatNames[3] != matName) - { - data.sharingMatNames[3] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y - 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if ((data.sharingMatNames[2] != matName) || (data.sharingMatNames[3] != matName)) - { - data.sharingMatNames[2] = matName; - data.sharingMatNames[3] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y - 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingMatNames[2] != matName) - { - data.sharingMatNames[2] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if ((data.sharingMatNames[1] != matName) || (data.sharingMatNames[3] != matName)) - { - data.sharingMatNames[1] = matName; - data.sharingMatNames[3] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[2] != matName)) - { - data.sharingMatNames[0] = matName; - data.sharingMatNames[2] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y + 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingMatNames[1] != matName) - { - data.sharingMatNames[1] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y + 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[1] != matName)) - { - data.sharingMatNames[0] = matName; - data.sharingMatNames[1] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - builderZoneRegion = this; - if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y + 1)) - { - LigoData data; - m_zoneBuilder->ligoData(data, zonePosU); - if (data.sharingMatNames[0] != matName) - { - data.sharingMatNames[0] = matName; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(data, zonePosU); - } - } - } - else - { - // Add modification landscape - if (dataZoneTempOriginal != dataZoneTemp) - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } -} - -void BuilderZoneRegion::setRot (sint32 x, sint32 y, uint8 rot) -{ - ZonePosition zonePosTemp(x, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.rot != rot) - { - dataZoneTemp.rot = rot; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } -} - -void BuilderZoneRegion::setFlip(sint32 x, sint32 y, uint8 flip) -{ - ZonePosition zonePosTemp(x, y, m_regionId); - LigoData dataZoneTemp; - m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); - if (dataZoneTemp.flip != flip) - { - dataZoneTemp.flip = flip; - - // Add modification landscape - m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); - } -} - - -void BuilderZoneRegion::reduceMin () -{ - const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); - sint32 i, j; - - sint32 newMinX = zoneRegion.getMinX(), newMinY = zoneRegion.getMinY (); - sint32 newMaxX = zoneRegion.getMaxX(), newMaxY = zoneRegion.getMaxY (); - bool bCanSuppr; - - // Reduce the MinY - while (true) - { - if (newMinY == newMaxY) - break; - j = newMinY; - bCanSuppr = true; - for (i = newMinX; i <= newMaxX; ++i) - { - std::string str = zoneRegion.getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - ++newMinY; - else - break; - } - - // Reduce the MaxY - while (true) - { - if (newMinY == newMaxY) - break; - j = newMaxY; - bCanSuppr = true; - for (i = newMinX; i <= newMaxX; ++i) - { - std::string str = zoneRegion.getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - --newMaxY; - else - break; - } - - // Reduce the MinX - while (true) - { - if (newMinX == newMaxX) - break; - i = newMinX; - bCanSuppr = true; - for (j = newMinY; j <= newMaxY; ++j) - { - std::string str = zoneRegion.getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - ++newMinX; - else - break; - } - - // Reduce the MaxX - while (true) - { - if (newMinX == newMaxX) - break; - i = newMaxX; - bCanSuppr = true; - for (j = newMinY; j <= newMaxY; ++j) - { - std::string str = zoneRegion.getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - --newMaxX; - else - break; - } - - if ((newMinX != zoneRegion.getMinX ()) || - (newMinY != zoneRegion.getMinY ()) || - (newMaxX != zoneRegion.getMaxX ()) || - (newMaxY != zoneRegion.getMaxY ())) - { - resize(newMinX, newMaxX, newMinY, newMaxY); - } -} - -uint BuilderZoneRegion::getRegionId() const -{ - return m_regionId; -} - -void BuilderZoneRegion::resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) -{ - const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); - if ((zoneRegion.getMinX ()!= newMinX) || - (zoneRegion.getMaxX ()!= newMaxX) || - (zoneRegion.getMinY ()!= newMinY) || - (zoneRegion.getMaxY ()!= newMaxY)) - { - m_zoneBuilder->actionLigoResize(m_regionId, newMinX, newMaxX, newMinY, newMaxY); - } -} - -void BuilderZoneRegion::placePiece(sint32 x, sint32 y, uint8 rot, uint8 flip, - NLLIGO::SPiece &sMask, NLLIGO::SPiece &sPosX, NLLIGO::SPiece &sPosY, - const std::string &eltName) -{ - for (int j = 0; j < sMask.h; ++j) - for (int i = 0; i < sMask.w; ++i) - if (sMask.Tab[i + j * sMask.w]) - { - set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName); - setRot(x + i, y + j, rot); - setFlip(x + i, y + j, flip); - } -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "builder_zone_region.h" +#include "builder_zone.h" +#include "zone_region_editor.h" + +// NeL includes +#include + +// Qt includes + +namespace LandscapeEditor +{ + +BuilderZoneRegion::BuilderZoneRegion(uint regionId) + : m_regionId(regionId), + m_zoneBuilder(0), + m_firstInit(false) +{ +} + +bool BuilderZoneRegion::init(ZoneBuilder *zoneBuilder) +{ + if (m_firstInit) + return true; + + m_zoneBuilder = zoneBuilder; + + uint32 j, k; + SMatNode mn; + std::vector AllValues; + + // Build the material tree + m_zoneBuilder->getZoneBank().getCategoryValues("material", AllValues); + for (uint32 i = 0; i < AllValues.size(); ++i) + { + mn.Name = AllValues[i]; + m_matTree.push_back(mn); + } + + // Link between materials + AllValues.clear (); + m_zoneBuilder->getZoneBank().getCategoryValues("transname", AllValues); + for (uint32 i = 0; i < AllValues.size(); ++i) + { + // Get the 2 materials linked together + std::string matAstr, matBstr; + for (j = 0; j < AllValues[i].size(); ++j) + { + if (AllValues[i][j] == '-') + break; + else + matAstr += AllValues[i][j]; + } + ++j; + for (; j < AllValues[i].size(); ++j) + matBstr += AllValues[i][j]; + + // Find matA + for (j = 0; j < m_matTree.size(); ++j) + if (m_matTree[j].Name == matAstr) + break; + + if (j < m_matTree.size()) + { + // Find matB + for (k = 0; k < m_matTree.size(); ++k) + if (m_matTree[k].Name == matBstr) + break; + + if (k < m_matTree.size()) + { + // Add a ref to matB in node matA + m_matTree[j].Arcs.push_back(k); + + // Add a ref to matA in node matB + m_matTree[k].Arcs.push_back(j); + } + } + } + + m_firstInit = true; + return true; +} + +class ToUpdate +{ + struct SElement + { + sint32 x, y; + + // Material put into the cell to update + std::string matPut; + + BuilderZoneRegion *builderZoneRegion; + }; + + std::vector m_elements; + +public: + + void add(BuilderZoneRegion *builderZoneRegion, sint32 x, sint32 y, const std::string &matName) + { + bool bFound = false; + for (uint32 m = 0; m < m_elements.size(); ++m) + if ((m_elements[m].x == x) && (m_elements[m].y == y)) + { + bFound = true; + break; + } + if (!bFound) + { + SElement newElement; + newElement.x = x; + newElement.y = y; + newElement.matPut = matName; + newElement.builderZoneRegion = builderZoneRegion; + m_elements.push_back (newElement); + } + } + + void del(sint32 x, sint32 y) + { + bool bFound = false; + uint32 m; + for (m = 0; m < m_elements.size(); ++m) + if ((m_elements[m].x == x) && (m_elements[m].y == y)) + { + bFound = true; + break; + } + if (bFound) + { + for (; m < m_elements.size() - 1; ++m) + m_elements[m] = m_elements[m + 1]; + m_elements.resize (m_elements.size() - 1); + } + } + + uint32 size() + { + return m_elements.size(); + } + + sint32 getX(uint32 m) + { + return m_elements[m].x; + } + + sint32 getY(uint32 m) + { + return m_elements[m].y; + } + + BuilderZoneRegion *getBuilderZoneRegion(uint32 m) + { + return m_elements[m].builderZoneRegion; + } + + const std::string &getMat (uint32 m) + { + return m_elements[m].matPut; + } +}; + +void BuilderZoneRegion::add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x,y)) + return; + + if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, rot, flip, zoneBankElement); + return; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize(sizeX * sizeY); + sPosX.Tab.resize(sizeX * sizeY); + sPosY.Tab.resize(sizeX * sizeY); + + for(j = 0; j < sizeY; ++j) + for(i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip(rot, flip); + sPosX.rotFlip(rot, flip); + sPosY.rotFlip(rot, flip); + + // Test if the pieces can be put (due to mask) + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + del(x + i, y + j, true, &tUpdate); + } + + // Delete all around all material that are not from the same as us + const std::string &curMat = zoneBankElement->getCategory("material"); + + if (curMat != STRING_NO_CAT_TYPE) + { + // This element is a valid material + // Place the piece + const std::string &eltName = zoneBankElement->getName(); + placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); + + // Put all transitions between different materials + putTransitions (x, y, sMask, curMat, &tUpdate); + placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); + } +} + +void BuilderZoneRegion::invertCutEdge(sint32 x, sint32 y, uint8 cePos) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); + if (zoneBankElement == NULL) + return; + if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + + ZonePosition zonePos(x, y, m_regionId); + LigoData dataZone; + + m_zoneBuilder->ligoData(dataZone, zonePos); + if (dataZone.sharingCutEdges[cePos] != 3 - dataZone.sharingCutEdges[cePos]) + { + dataZone.sharingCutEdges[cePos] = 3 - dataZone.sharingCutEdges[cePos]; + + m_zoneBuilder->actionLigoTile(dataZone, zonePos); + } + updateTrans(x, y); + + // If the transition number is not the same propagate the change + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (cePos == 2) + if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[2]) + { + if (x > zoneRegion.getMinX ()) + { + // [x-1][y].right = [x][y].left + // _Zones[(x-1-zoneRegion->getMinX ())+(y-zoneRegion->getMinY ())*stride].SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; + ZonePosition zonePosTemp(x - 1, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[3] != dataZone.sharingCutEdges[2]) + { + dataZoneTemp.sharingCutEdges[3] = dataZone.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x - 1, y); + } + if (cePos == 3) + if (dataZone.sharingMatNames[1] != dataZone.sharingMatNames[3]) + { + if (x < zoneRegion.getMaxX ()) + { + // [x+1][y].left = [x][y].right + ZonePosition zonePosTemp(x + 1, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[2] != dataZone.sharingCutEdges[3]) + { + dataZoneTemp.sharingCutEdges[2] = dataZone.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x + 1, y); + } + if (cePos == 1) + if (dataZone.sharingMatNames[0] != dataZone.sharingMatNames[1]) + { + if (y > zoneRegion.getMinY ()) + { + // [x][y-1].up = [x][y].down + ZonePosition zonePosTemp(x, y - 1, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[0] != dataZone.sharingCutEdges[1]) + { + dataZoneTemp.sharingCutEdges[0] = dataZone.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x, y-1); + } + if (cePos == 0) + if (dataZone.sharingMatNames[2] != dataZone.sharingMatNames[3]) + { + if (y < zoneRegion.getMaxY ()) + { + // [x][y+1].down = [x][y].up + ZonePosition zonePosTemp(x, y + 1, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.sharingCutEdges[1] != dataZone.sharingCutEdges[0]) + { + dataZoneTemp.sharingCutEdges[1] = dataZone.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + } + updateTrans (x, y + 1); + } +} + +void BuilderZoneRegion::cycleTransition(sint32 x, sint32 y) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x, y)); + if (zoneBankElement == NULL) + return; + if (zoneBankElement->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + // \todo trap -> choose the good transition in function of the transition under the current location + // Choose the next possible transition if not the same as the first one + // Choose among all transition of the same number + + updateTrans (x, y); +} + +bool BuilderZoneRegion::addNotPropagate (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return false; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x, y)) + return false; + + if (zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, rot, flip, zoneBankElement); + return true; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX * sizeY); + sPosX.Tab.resize (sizeX * sizeY); + sPosY.Tab.resize (sizeX * sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (rot, flip); + sPosX.rotFlip (rot, flip); + sPosY.rotFlip (rot, flip); + + // Test if the pieces can be put (due to mask) + sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x + i, y + j) == false) + return false; + if (((x + i) < zoneRegion.getMinX ()) || ((x + i) > zoneRegion.getMaxX ()) || + ((y + j) < zoneRegion.getMinY ()) || ((y + j) > zoneRegion.getMaxY ())) + return false; + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + j)); + if (zoneBankElementUnder == NULL) + return false; + if (zoneBankElementUnder->getCategory("material") != zoneBankElement->getCategory("material")) + return false; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + del(x + i, y + j, true, &tUpdate); + } + + const std::string &curMat = zoneBankElement->getCategory("material"); + + if (curMat != STRING_NO_CAT_TYPE) + { + // This element is a valid material + // Place the piece + const std::string &eltName = zoneBankElement->getName(); + placePiece(x, y, rot, flip, sMask, sPosX, sPosY, eltName); + } + + return true; +} + +void BuilderZoneRegion::addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 i, j; + NLLIGO::SPiece sMask, sPosX, sPosY; + ToUpdate tUpdate; // Transition to update + + if (!m_zoneBuilder->getZoneMask (x, y)) + return; + + /* + if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, nRot, nFlip, pElt); + return; + }*/ + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX * sizeY); + sPosX.Tab.resize (sizeX * sizeY); + sPosY.Tab.resize (sizeX * sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i + j * sizeX] = (uint8)i; + sPosY.Tab[i + j * sizeX] = (uint8)j; + sMask.Tab[i + j * sizeX] = zoneBankElement->getMask()[i + j * sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (rot, flip); + sPosX.rotFlip (rot, flip); + sPosY.rotFlip (rot, flip); + + // Test if the pieces can be put (due to mask) + // All space under the mask must be empty + sint32 stride = (1 + zoneRegion.getMaxX () - zoneRegion.getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (m_zoneBuilder->getZoneMask(x+i, y+j) == false) + return; + if (((x+i) < zoneRegion.getMinX ()) || ((x+i) > zoneRegion.getMaxX ()) || + ((y+j) < zoneRegion.getMinY ()) || ((y+j) > zoneRegion.getMaxY ())) + return; + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName (x + i, y + i)); + if (zoneBankElementUnder != NULL) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + del(x+i, y+j, true, &tUpdate); + } + + const std::string &curMat = zoneBankElement->getCategory ("material"); + const bool transition = zoneBankElement->getCategory("transname") != STRING_NO_CAT_TYPE; + + if (curMat != STRING_NO_CAT_TYPE || transition) + { + // This element is a valid material + // Place the piece + const std::string &eltName = zoneBankElement->getName(); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName, transition); + setRot(x + i, y + j, rot); + setFlip(x + i, y + j, flip); + } + } +} + +uint8 TransToEdge[72][4] = +{ + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 0, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 0, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 3 + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 1, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 1, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 3 + + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 0 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 1 + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 2 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 3 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 0 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 1 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 2 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 3 + + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 0, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 0, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 3 + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 1, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 1, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 1, Rot = 3 +}; + +void BuilderZoneRegion::addTransition (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + uint32 i; + // Check that we write in an already defined place + if ((x < zoneRegion.getMinX ()) || (x > zoneRegion.getMaxX ()) || + (y < zoneRegion.getMinY ()) || (y > zoneRegion.getMaxY ())) + return; + + // Check size + if ((zoneBankElement->getSizeX() != 1) || (zoneBankElement->getSizeY() != 1)) + return; + + // Check that an element already exist at position we want put the transition + NLLIGO::CZoneBankElement *zoneBankElementUnder = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneRegion.getName(x, y)); + if (zoneBankElementUnder == NULL) + return; + + // And check that this element is also a transition and the same transition + if (zoneBankElementUnder->getCategory ("transname") == STRING_NO_CAT_TYPE) + return; + if (zoneBankElementUnder->getCategory ("transname") != zoneBankElement->getCategory("transname")) + return; + + std::string underType = zoneBankElementUnder->getCategory("transtype"); + std::string overType = zoneBankElement->getCategory("transtype"); + std::string underNum = zoneBankElementUnder->getCategory("transnum"); + std::string overNum = zoneBankElement ->getCategory("transnum"); + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneOriginal = dataZoneTemp; + + bool bMustPropagate = false; + // Same type of transition ? + if (zoneBankElementUnder->getCategory("transtype") != zoneBankElement->getCategory("transtype")) + { + // No so random the cutEdges + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); + NLMISC::clamp(nCut, (uint8)1, (uint8)2); + + dataZoneTemp.sharingCutEdges[i] = nCut; + } + zoneBankElement = NULL; + bMustPropagate = true; + } + else + { + // Put exactly the transition as given + sint32 transnum = atoi(zoneBankElement->getCategory("transnum").c_str()); + sint32 flip = zoneRegion.getFlip(x, y); + sint32 rot = zoneRegion.getRot(x, y); + sint32 pos1 = -1, pos2 = -1; + + for (i = 0; i < 4; ++i) + { + if ((TransToEdge[transnum * 8 + flip * 4 + rot][i] != 0) && + (TransToEdge[transnum * 8 + flip * 4 + rot][i] != dataZoneTemp.sharingCutEdges[i])) + bMustPropagate = true; + + dataZoneTemp.sharingCutEdges[i] = TransToEdge[transnum * 8 + flip * 4 + rot][i]; + + if ((pos1 != -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) + pos2 = i; + if ((pos1 == -1) && (dataZoneTemp.sharingCutEdges[i] != 0)) + pos1 = i; + } + // Exchange cutedges != 0 one time /2 to permit all positions + if ((transnum == 1) || (transnum == 4) || (transnum == 7)) + if (zoneBankElement->getName() == zoneBankElementUnder->getName()) + { + bMustPropagate = true; + + dataZoneTemp.sharingCutEdges[pos1] = 3 - dataZoneTemp.sharingCutEdges[pos1]; + dataZoneTemp.sharingCutEdges[pos2] = 3 - dataZoneTemp.sharingCutEdges[pos2]; + } + } + if (dataZoneTemp != dataZoneOriginal) + { + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } + updateTrans (x, y, zoneBankElement); + + // If the transition number is not the same propagate the change + if (bMustPropagate) + { + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) + { + if (x > zoneRegion.getMinX ()) + { + // [x-1][y].right = [x][y].left + // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; + ZonePosition zonePosTemp2(x - 1, y, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) + { + dataZoneTemp2.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x - 1, y); + } + if (dataZoneTemp.sharingMatNames[1] != dataZoneTemp.sharingMatNames[3]) + { + if (x < zoneRegion.getMaxX ()) + { + // [x+1][y].left = [x][y].right + //_Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; + ZonePosition zonePosTemp2(x + 1, y, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) + { + dataZoneTemp2.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x + 1, y); + } + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) + { + if (y > zoneRegion.getMinY ()) + { + // [x][y-1].up = [x][y].down + //_Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; + ZonePosition zonePosTemp2(x, y - 1, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) + { + dataZoneTemp2.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x, y - 1); + } + if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) + { + if (y < zoneRegion.getMaxY ()) + { + // [x][y+1].down = [x][y].up + //_Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; + ZonePosition zonePosTemp2(x, y + 1, m_regionId); + LigoData dataZoneTemp2; + m_zoneBuilder->ligoData(dataZoneTemp2, zonePosTemp2); + if (dataZoneTemp2.sharingCutEdges[1] != dataZoneTemp.sharingCutEdges[0]) + { + dataZoneTemp2.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp2, zonePosTemp2); + } + } + updateTrans (x, y + 1); + } + } +} + +void BuilderZoneRegion::addToUpdateAndCreate(BuilderZoneRegion *builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, + const std::string &newMat, ToUpdate *ptCreate, ToUpdate *ptUpdate) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + sint32 stride = (1 + zoneRegion.getMaxX() - zoneRegion.getMinX()); + + ZonePosition zonePos; + if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion, x, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePos); + if (data.sharingMatNames[sharePos] != newMat) + { + data.sharingMatNames[sharePos] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePos); + } + builderZoneRegion->del(x, y, true, ptUpdate); + ptCreate->add(builderZoneRegion, x, y, newMat); + } +} + +void BuilderZoneRegion::putTransitions (sint32 inX, sint32 inY, const NLLIGO::SPiece &mask, const std::string &matName, + ToUpdate *ptUpdate) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + ToUpdate tCreate; // Transition to create + + sint32 i, j, k, l, m; + sint32 x = inX, y = inY; + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + for (k = -1; k <= 1; ++k) + for (l = -1; l <= 1; ++l) + { + BuilderZoneRegion *builderZoneRegion2 = this; + ZonePosition zonePos; + if (m_zoneBuilder->getZoneAmongRegions(zonePos, builderZoneRegion2, inX + i + l, inY + j + k)) + tCreate.add(builderZoneRegion2, inX + i + l, inY + j + k, matName); + } + } + + // Check coherency of the transition to update + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + BuilderZoneRegion *builderZoneRegion2 = tCreate.getBuilderZoneRegion(m); + x = tCreate.getX(m); + y = tCreate.getY(m); + std::string putMat = tCreate.getMat(m); + + //if ((x < pBZR->getMinX ())||(x > pBZR->getMaxX ())||(y < pBZR->getMinY ())||(y > pBZR->getMaxY ())) + // continue; + + ZonePosition zoneTemp(x, y, builderZoneRegion2->getRegionId()); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + + if (!((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[1])&& + (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2])&& + (dataZoneTemp.sharingMatNames[2] == dataZoneTemp.sharingMatNames[3]))) + builderZoneRegion2->del(x, y, true, ptUpdate); + + // Check to see material can be posed + uint corner; + for (corner = 0; corner < 4; corner++) + { + std::string newMat = getNextMatInTree (putMat, dataZoneTemp.sharingMatNames[corner]); + + // Can't be posed ? + if (newMat == STRING_UNUSED) + break; + } + if ( (corner < 4) && (m != 0) ) + { + // The material can't be paused + for (int t = 0; t < 4; ++t) + dataZoneTemp.sharingMatNames[t] = STRING_UNUSED; + + // Don't propagate any more + } + else + { + // Expand material for the 1st quarter + std::string newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[0]); + if (newMat != dataZoneTemp.sharingMatNames[0]) + { + // Update the quarter + if (dataZoneTemp.sharingMatNames[0] != newMat) + { + dataZoneTemp.sharingMatNames[0] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y - 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 2, x, y - 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 2nd quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[1]); + if (newMat != dataZoneTemp.sharingMatNames[1]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[1] != newMat) + { + dataZoneTemp.sharingMatNames[1] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y - 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 3, x, y - 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 3rd quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[2]); + if (newMat != dataZoneTemp.sharingMatNames[2]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[2] != newMat) + { + dataZoneTemp.sharingMatNames[2] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 3, x - 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 1, x - 1, y + 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 0, x, y + 1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 4th quarter + newMat = getNextMatInTree(putMat, dataZoneTemp.sharingMatNames[3]); + if (newMat != dataZoneTemp.sharingMatNames[3]) + { + // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.sharingMatNames[3] != newMat) + { + dataZoneTemp.sharingMatNames[3] = newMat; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + addToUpdateAndCreate(builderZoneRegion2, 2, x + 1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 0, x + 1, y + 1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate(builderZoneRegion2, 1, x, y + 1, newMat, &tCreate, ptUpdate); + } + } + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + + // Delete transitions that are inside the mask + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + tCreate.del(inX + i, inY + j); + } + + // For all transition to update choose the cut edge + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + ZoneRegionObject *zoneRegionObj2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId()); + if (zoneRegionObj2 == 0) + continue; + + const NLLIGO::CZoneRegion &zoneRegion2 = zoneRegionObj2->ligoZoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + continue; + + ZonePosition zoneTemp(x, y, tCreate.getBuilderZoneRegion(m)->getRegionId()); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f + NLMISC::frand(2.0f)); + NLMISC::clamp(nCut, (uint8)1, (uint8)2); + dataZoneTemp.sharingCutEdges[i] = nCut; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + + // Propagate + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[2]) + { + // [x-1][y].right = [x][y].left + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x - 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[3] != dataZoneTemp.sharingCutEdges[2]) + { + data.sharingCutEdges[3] = dataZoneTemp.sharingCutEdges[2]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add(builderZoneRegion3, x - 1, y, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[2] != 0) + { + dataZoneTemp.sharingCutEdges[2] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1]) + { + // [x][y-1].up = [x][y].down + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[0] != dataZoneTemp.sharingCutEdges[1]) + { + data.sharingCutEdges[0] = dataZoneTemp.sharingCutEdges[1]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add (builderZoneRegion3, x, y - 1, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[1] != 0) + { + dataZoneTemp.sharingCutEdges[1] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[3] != dataZoneTemp.sharingMatNames[1]) + { + // [x+1][y].left = [x][y].right + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion3, x + 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[2] != dataZoneTemp.sharingCutEdges[3]) + { + data.sharingCutEdges[2] = dataZoneTemp.sharingCutEdges[3]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add(builderZoneRegion3, x + 1, y, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[3] != 0) + { + dataZoneTemp.sharingCutEdges[3] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + + if (dataZoneTemp.sharingMatNames[2] != dataZoneTemp.sharingMatNames[3]) + { + // [x][y+1].down = [x][y].up + BuilderZoneRegion *builderZoneRegion3 = tCreate.getBuilderZoneRegion(m); + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions (zonePosU, builderZoneRegion3, x, y+1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]) + { + data.sharingCutEdges[1] = dataZoneTemp.sharingCutEdges[0]; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + ptUpdate->add (builderZoneRegion3, x, y + 1, ""); + } + } + else + { + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + if (dataZoneTemp.sharingCutEdges[0] = 0) + { + dataZoneTemp.sharingCutEdges[0] = 0; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zoneTemp); + } + } + } + + // Delete in tUpdate each element in common with tCreate + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + x = tCreate.getX(m); + y = tCreate.getY(m); + ptUpdate->del (x,y); + } + + // Finally update all transition + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && + (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) + tCreate.getBuilderZoneRegion(m)->updateTrans(x, y); + } + + // WARNING: TODO: check this for + for (m = 0; m < (sint32)ptUpdate->size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(ptUpdate->getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); + x = ptUpdate->getX(m); + y = ptUpdate->getY(m); + if ((x >= zoneRegion2.getMinX()) && (x <= zoneRegion2.getMaxX()) && + (y >= zoneRegion2.getMinY()) && (y <= zoneRegion2.getMaxY())) + ptUpdate->getBuilderZoneRegion(m)->updateTrans(x, y); + } + + // Cross material + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const NLLIGO::CZoneRegion &zoneRegion2 = m_zoneBuilder->zoneRegion(tCreate.getBuilderZoneRegion(m)->getRegionId())->ligoZoneRegion(); + x = tCreate.getX(m); + y = tCreate.getY(m); + + + ZonePosition zoneTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zoneTemp); + + std::set matNameSet; + for (i = 0; i < 4; ++i) + matNameSet.insert(dataZoneTemp.sharingMatNames[i]); + + if (((dataZoneTemp.sharingMatNames[0] == dataZoneTemp.sharingMatNames[3]) && + (dataZoneTemp.sharingMatNames[1] == dataZoneTemp.sharingMatNames[2]) && + (dataZoneTemp.sharingMatNames[0] != dataZoneTemp.sharingMatNames[1])) + || (matNameSet.size()>2)) + { + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection(); + zoneBank.addOrSwitch("material", tCreate.getMat(m)); + zoneBank.addAndSwitch("size", "1x1"); + std::vector vElts; + zoneBank.getSelection(vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp(nRan, (sint32)0, (sint32)(vElts.size() - 1)); + NLLIGO::CZoneBankElement *zoneBankElement = vElts[nRan]; + nRan = (uint32)(NLMISC::frand (1.0) * 4); + NLMISC::clamp(nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand (1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + tCreate.getBuilderZoneRegion(m)->add(x, y, rot, flip, zoneBankElement); + } + } +} + +struct STrans +{ + uint8 Num; + uint8 Rot; + uint8 Flip; +}; + +STrans TranConvTable[128] = +{ + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 1 UNUSED + + { 6,0,0 }, // Quart = 1, CutEdge = 0, Np = 0 + { 6,3,1 }, // Quart = 1, CutEdge = 0, Np = 1 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 0 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 1 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 0 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 1 + { 8,0,0 }, // Quart = 1, CutEdge = 3, Np = 0 + { 8,3,1 }, // Quart = 1, CutEdge = 3, Np = 1 + + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 0 + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 1 + { 6,0,1 }, // Quart = 2, CutEdge = 1, Np = 0 + { 6,1,0 }, // Quart = 2, CutEdge = 1, Np = 1 + { 8,1,0 }, // Quart = 2, CutEdge = 2, Np = 0 + { 8,0,1 }, // Quart = 2, CutEdge = 2, Np = 1 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 0 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 3, CutEdge = 0, Np = 0 + { 0,0,1 }, // Quart = 3, CutEdge = 0, Np = 1 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 0 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 1 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 0 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 1 + { 2,0,0 }, // Quart = 3, CutEdge = 3, Np = 0 + { 2,0,1 }, // Quart = 3, CutEdge = 3, Np = 1 + + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 0 + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 1 + { 8,3,0 }, // Quart = 4, CutEdge = 1, Np = 0 + { 8,2,1 }, // Quart = 4, CutEdge = 1, Np = 1 + { 6,3,0 }, // Quart = 4, CutEdge = 2, Np = 0 + { 6,2,1 }, // Quart = 4, CutEdge = 2, Np = 1 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 0 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 1 + + { 0,3,0 }, // Quart = 5, CutEdge = 0, Np = 0 + { 0,3,1 }, // Quart = 5, CutEdge = 0, Np = 1 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 0 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 1 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 0 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 1 + { 2,3,0 }, // Quart = 5, CutEdge = 3, Np = 0 + { 2,3,1 }, // Quart = 5, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 1 UNUSED + + { 5,2,0 }, // Quart = 7, CutEdge = 0, Np = 0 + { 5,1,1 }, // Quart = 7, CutEdge = 0, Np = 1 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 0 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 1 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 0 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 1 + { 3,2,0 }, // Quart = 7, CutEdge = 3, Np = 0 + { 3,1,1 }, // Quart = 7, CutEdge = 3, Np = 1 + + { 8,2,0 }, // Quart = 8, CutEdge = 0, Np = 0 + { 8,1,1 }, // Quart = 8, CutEdge = 0, Np = 1 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 0 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 1 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 0 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 1 + { 6,2,0 }, // Quart = 8, CutEdge = 3, Np = 0 + { 6,1,1 }, // Quart = 8, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 1 UNUSED + + { 2,1,0 }, // Quart = 10, CutEdge = 0, Np = 0 + { 2,1,1 }, // Quart = 10, CutEdge = 0, Np = 1 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 0 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 1 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 0 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 1 + { 0,1,0 }, // Quart = 10, CutEdge = 3, Np = 0 + { 0,1,1 }, // Quart = 10, CutEdge = 3, Np = 1 + + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 0 + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 1 + { 5,3,0 }, // Quart = 11, CutEdge = 1, Np = 0 + { 5,2,1 }, // Quart = 11, CutEdge = 1, Np = 1 + { 3,3,0 }, // Quart = 11, CutEdge = 2, Np = 0 + { 3,2,1 }, // Quart = 11, CutEdge = 2, Np = 1 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 0 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 1 + + { 2,2,0 }, // Quart = 12, CutEdge = 0, Np = 0 + { 2,2,1 }, // Quart = 12, CutEdge = 0, Np = 1 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 0 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 1 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 0 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 1 + { 0,2,0 }, // Quart = 12, CutEdge = 3, Np = 0 + { 0,2,1 }, // Quart = 12, CutEdge = 3, Np = 1 + + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 0 + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 1 + { 3,1,0 }, // Quart = 13, CutEdge = 1, Np = 0 + { 3,0,1 }, // Quart = 13, CutEdge = 1, Np = 1 + { 5,1,0 }, // Quart = 13, CutEdge = 2, Np = 0 + { 5,0,1 }, // Quart = 13, CutEdge = 2, Np = 1 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 0 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 1 + + { 3,0,0 }, // Quart = 14, CutEdge = 0, Np = 0 + { 3,3,1 }, // Quart = 14, CutEdge = 0, Np = 1 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 0 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 1 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 0 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 1 + { 5,0,0 }, // Quart = 14, CutEdge = 3, Np = 0 + { 5,3,1 }, // Quart = 14, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 } // Quart = 15, CutEdge = 3, Np = 1 UNUSED +}; + +void BuilderZoneRegion::updateTrans (sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + return; + + //if (!_Builder->getZoneMask(x,y)) + // return; + + // Interpret the transition info + x -= zoneRegion.getMinX (); + y -= zoneRegion.getMinY (); + sint32 m; + + // Calculate the number of material around with transition info + std::set matNameSet; + + ZonePosition zonePosTemp(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + for (m = 0; m < 4; ++m) + matNameSet.insert(dataZoneTemp.sharingMatNames[m]); + + if (matNameSet.size() == 1) + { + if (dataZoneTemp.sharingMatNames[0] == STRING_UNUSED) + { + del(x + zoneRegion.getMinX (), y + zoneRegion.getMinY ()); + // set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, STRING_UNUSED, false); + return; + } + else + { + NLLIGO::CZoneBankElement *zoneBankElement2 = m_zoneBuilder->getZoneBank().getElementByZoneName(dataZoneTemp.zoneName); + if ((zoneBankElement != NULL) && (zoneBankElement2 != NULL) && (zoneBankElement2->getCategory("material") == dataZoneTemp.sharingMatNames[0])) + return; + + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection (); + zoneBank.addOrSwitch ("material", dataZoneTemp.sharingMatNames[0]); + zoneBank.addAndSwitch ("size", "1x1"); + std::vector vElts; + zoneBank.getSelection (vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); + zoneBankElement = vElts[nRan]; + nRan = (uint32)(NLMISC::frand(1.0) * 4); + NLMISC::clamp (nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand(1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + set(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), 0, 0, zoneBankElement->getName(), false); + setRot(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), rot); + setFlip(x + zoneRegion.getMinX(), y + zoneRegion.getMinY(), flip); + return; + } + } + + // No 2 materials so the transition system dont work + if (matNameSet.size() != 2) + return; + + std::set::iterator it = matNameSet.begin(); + std::string matA = *it; + ++it; + std::string matB = *it; + + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection (); + zoneBank.addOrSwitch("transname", matA + "-" + matB); + std::vector selection; + zoneBank.getSelection(selection); + if (selection.size() == 0) + { + std::string matTmp = matA; + matA = matB; + matB = matTmp; + zoneBank.resetSelection (); + zoneBank.addOrSwitch ("transname", matA + "-" + matB); + zoneBank.getSelection (selection); + } + + if (selection.size() == 0) + return; + + // Convert the sharingCutEdges and SharingNames to the num and type of transition + uint8 nQuart = 0; // 0-MatA 1-MatB + for (m = 0; m < 4; ++m) + if (dataZoneTemp.sharingMatNames[m] == matB) + nQuart |= (1 << m); + + if ((nQuart == 0) || (nQuart == 6) || + (nQuart == 9) || (nQuart == 15)) + return; // No transition for those types + + uint8 nCutEdge = 0; + uint8 nPosCorner = 0; + + // If up edge is cut write the cut position in nCutEdge bitfield (1->0, 2->1) + if ((nQuart == 4) || (nQuart == 5) || + (nQuart == 7) || (nQuart == 8) || + (nQuart == 10) || (nQuart == 11)) + { + if (dataZoneTemp.sharingCutEdges[0] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[0] = 0; + } + + // Same for down edge + if ((nQuart == 1) || (nQuart == 2) || + (nQuart == 5) || (nQuart == 10) || + (nQuart == 13) || (nQuart == 14)) + { + if (dataZoneTemp.sharingCutEdges[1] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[1] = 0; + } + + // Same for left edge + if ((nQuart == 1) || (nQuart == 3) || + (nQuart == 4) ||(nQuart == 11) || + (nQuart == 12) || (nQuart == 14)) + { + if (dataZoneTemp.sharingCutEdges[2] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[2] = 0; + } + + // Same for right edge + if ((nQuart == 2) || (nQuart == 3) || + (nQuart == 7) || (nQuart == 8) || + (nQuart == 12) || (nQuart == 13)) + { + if (dataZoneTemp.sharingCutEdges[3] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.sharingCutEdges[3] = 0; + } + + nlassert (nPosCorner == 2); // If not this means that more than 2 edges are cut which is not possible + + STrans Trans, TransTmp1, TransTmp2; + + TransTmp1 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 0]; + TransTmp2 = TranConvTable[nQuart * 8 + 2 * nCutEdge + 1]; + + // Choose one or the two + sint32 nTrans = (sint32)(NLMISC::frand(2.0f)); + NLMISC::clamp(nTrans, (sint32)0, (sint32)1); + if (nTrans == 0) + Trans = TransTmp1; + else + Trans = TransTmp2; + + zoneBank.addAndSwitch ("transnum", NLMISC::toString(Trans.Num)); + zoneBank.getSelection (selection); + + if (selection.size() > 0) + { + if (zoneBankElement != NULL) + { + dataZoneTemp.zoneName = zoneBankElement->getName(); + } + else + { + nTrans = (uint32)(NLMISC::frand (1.0) * selection.size()); + NLMISC::clamp(nTrans, (sint32)0, (sint32)(selection.size() - 1)); + dataZoneTemp.zoneName = selection[nTrans]->getName(); + } + dataZoneTemp.posX = dataZoneTemp.posY = 0; + dataZoneTemp.rot = Trans.Rot; + dataZoneTemp.flip = Trans.Flip; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); +} + +std::string BuilderZoneRegion::getNextMatInTree (const std::string &matA, const std::string &matB) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); + uint32 i, posA = 10000, posB = 10000; + + if (matA == matB) + return matA; + + for (i = 0; i < m_matTree.size(); ++i) + { + if (m_matTree[i].Name == matA) + posA = i; + if (m_matTree[i].Name == matB) + posB = i; + } + if ((posA == 10000) || (posB == 10000)) + return STRING_UNUSED; + + std::vector vTemp; + tryPath (posA, posB, vTemp); + if (vTemp.size() <= 1) + return STRING_UNUSED; + else + return m_matTree[vTemp[1]].Name; +} + +struct SNode +{ + sint32 NodePos, Dist, PrevNodePos; + + SNode() + { + NodePos = Dist = PrevNodePos = -1; + } +}; + +void BuilderZoneRegion::tryPath(uint32 posA, uint32 posB, std::vector &path) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + + // Build the adjascence matrix + std::vector matAdj; + sint32 numNodes = m_matTree.size(); + sint32 i, j, cost; + matAdj.resize(numNodes * numNodes, -1); + for (i = 0; i < numNodes; ++i) + for (j = 0; j < (sint32)m_matTree[i].Arcs.size(); ++j) + matAdj[i + m_matTree[i].Arcs[j] * numNodes] = 1; + + std::vector vNodes; // NodesPos == index + vNodes.resize (numNodes); + for (i = 0; i < numNodes; ++i) + vNodes[i].NodePos = i; + vNodes[posA].Dist = 0; + + std::queue qNodes; + qNodes.push (vNodes[posA]); + + while (qNodes.size() > 0) + { + SNode node = qNodes.front(); + qNodes.pop (); + + for (i = 0; i < numNodes; ++i) + { + cost = matAdj[node.NodePos + i * numNodes]; + if (cost != -1) + { + if ((vNodes[i].Dist == -1) || (vNodes[i].Dist > (cost + node.Dist))) + { + vNodes[i].Dist = cost + node.Dist; + vNodes[i].PrevNodePos = node.NodePos; + qNodes.push(vNodes[i]); + } + } + } + } + + // Get path length + i = posB; + j = 0; + while (i != -1) + { + ++j; + i = vNodes[i].PrevNodePos; + } + + // Write the path in the good order (from posA to posB) + path.resize(j); + i = posB; + while (i != -1) + { + --j; + path[j] = i; + i = vNodes[i].PrevNodePos; + } +} + +void BuilderZoneRegion::del(sint32 x, sint32 y, bool transition, ToUpdate *pUpdate) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + if (!m_zoneBuilder->getZoneMask(x, y)) + return; + + const std::string &nameZone = zoneRegion.getName(x, y); + NLLIGO::CZoneBankElement *zoneBankElement = m_zoneBuilder->getZoneBank().getElementByZoneName(nameZone); + if (zoneBankElement != NULL) + { + sint32 sizeX = zoneBankElement->getSizeX(), sizeY = zoneBankElement->getSizeY(); + sint32 posX = zoneRegion.getPosX (x, y), posY = zoneRegion.getPosY (x, y); + uint8 rot = zoneRegion.getRot (x, y); + uint8 flip = zoneRegion.getFlip (x, y); + sint32 i, j; + sint32 deltaX, deltaY; + + if (flip == 0) + { + switch (rot) + { + case 0: + deltaX = -posX; + deltaY = -posY; + break; + case 1: + deltaX = -(sizeY - 1 - posY); + deltaY = -posX; + break; + case 2: + deltaX = -(sizeX - 1 - posX); + deltaY = -(sizeY - 1 - posY); + break; + case 3: + deltaX = -posY; + deltaY = -(sizeX - 1 - posX); + break; + } + } + else + { + switch (rot) + { + case 0: + deltaX = -(sizeX - 1 - posX); + deltaY = -posY; + break; + case 1: + deltaX = -(sizeY - 1 - posY); + deltaY = -(sizeX - 1 - posX); + break; + case 2: + deltaX = -posX; + deltaY = -(sizeY - 1 - posY); + break; + case 3: + deltaX = -posY; + deltaY = -posX; + break; + } + } + + NLLIGO::SPiece mask; + mask.Tab.resize (sizeX * sizeY); + for(i = 0; i < sizeX * sizeY; ++i) + mask.Tab[i] = zoneBankElement->getMask()[i]; + mask.w = sizeX; + mask.h = sizeY; + mask.rotFlip (rot, flip); + + for (j = 0; j < mask.h; ++j) + for (i = 0; i < mask.w; ++i) + if (mask.Tab[i + j * mask.w]) + { + set(x + deltaX + i, y + deltaY + j, 0, 0, STRING_UNUSED, true); + setRot(x + deltaX + i, y + deltaY + j, 0); + setFlip(x + deltaX + i, y + deltaY + j, 0); + if (pUpdate != NULL) + { + pUpdate->add(this, x + deltaX + i, y + deltaY + j, ""); + } + } + if (!transition) + reduceMin (); + } + else + { + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + return; + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + LigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.zoneName = STRING_UNUSED; + dataZoneTemp.posX = 0; + dataZoneTemp.posY = 0; + + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.sharingMatNames[i] = STRING_UNUSED; + dataZoneTemp.sharingCutEdges[i] = 0; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + + } +} + +void BuilderZoneRegion::move (sint32 x, sint32 y) +{ + m_zoneBuilder->actionLigoMove(m_regionId, x, y); +} + +uint32 BuilderZoneRegion::countZones () +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); + sint32 x, y; + + uint32 counter = 0; + + for (y = zoneRegion.getMinY (); y <= zoneRegion.getMaxY (); ++y) + for (x = zoneRegion.getMinX (); x <= zoneRegion.getMaxX (); ++x) + if (zoneRegion.getName (x, y) != STRING_UNUSED) + ++counter; + + return counter; +} + +void BuilderZoneRegion::set(sint32 x, sint32 y, sint32 posX, sint32 posY, + const std::string &zoneName, bool transition) +{ + ZoneRegionObject *zoneRegionObj = m_zoneBuilder->zoneRegion(m_regionId); + if (zoneRegionObj == 0) + return; + + const NLLIGO::CZoneRegion &zoneRegion = zoneRegionObj->ligoZoneRegion(); + + // Do we need to resize ? + if ((x < zoneRegion.getMinX()) || (x > zoneRegion.getMaxX()) || + (y < zoneRegion.getMinY()) || (y > zoneRegion.getMaxY())) + { + sint32 newMinX = (x < zoneRegion.getMinX() ? x: zoneRegion.getMinX()), newMinY = (y < zoneRegion.getMinY() ? y: zoneRegion.getMinY()); + sint32 newMaxX = (x > zoneRegion.getMaxX() ? x: zoneRegion.getMaxX()), newMaxY = (y > zoneRegion.getMaxY() ? y: zoneRegion.getMaxY()); + + resize(newMinX, newMaxX, newMinY, newMaxY); + } + + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + if (!m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp)) + return; + LigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.zoneName = zoneName; + dataZoneTemp.posX = (uint8)posX; + dataZoneTemp.posY = (uint8)posY; + + if (!transition) + { + NLLIGO::CZoneBankElement *zoneBankElem = m_zoneBuilder->getZoneBank().getElementByZoneName(zoneName); + if (zoneBankElem == NULL) + return; + + const std::string &matName = zoneBankElem->getCategory ("material"); + if (matName == STRING_NO_CAT_TYPE) + return; + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.sharingMatNames[i] = matName; + dataZoneTemp.sharingCutEdges[i] = 0; + } + + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + + BuilderZoneRegion *builderZoneRegion = this; + ZonePosition zonePosU; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[3] != matName) + { + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[2] != matName) || (data.sharingMatNames[3] != matName)) + { + data.sharingMatNames[2] = matName; + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y - 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[2] != matName) + { + data.sharingMatNames[2] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[1] != matName) || (data.sharingMatNames[3] != matName)) + { + data.sharingMatNames[1] = matName; + data.sharingMatNames[3] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[2] != matName)) + { + data.sharingMatNames[0] = matName; + data.sharingMatNames[2] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x - 1, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[1] != matName) + { + data.sharingMatNames[1] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if ((data.sharingMatNames[0] != matName) || (data.sharingMatNames[1] != matName)) + { + data.sharingMatNames[0] = matName; + data.sharingMatNames[1] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + builderZoneRegion = this; + if (m_zoneBuilder->getZoneAmongRegions(zonePosU, builderZoneRegion, x + 1, y + 1)) + { + LigoData data; + m_zoneBuilder->ligoData(data, zonePosU); + if (data.sharingMatNames[0] != matName) + { + data.sharingMatNames[0] = matName; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(data, zonePosU); + } + } + } + else + { + // Add modification landscape + if (dataZoneTempOriginal != dataZoneTemp) + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + +void BuilderZoneRegion::setRot (sint32 x, sint32 y, uint8 rot) +{ + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.rot != rot) + { + dataZoneTemp.rot = rot; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + +void BuilderZoneRegion::setFlip(sint32 x, sint32 y, uint8 flip) +{ + ZonePosition zonePosTemp(x, y, m_regionId); + LigoData dataZoneTemp; + m_zoneBuilder->ligoData(dataZoneTemp, zonePosTemp); + if (dataZoneTemp.flip != flip) + { + dataZoneTemp.flip = flip; + + // Add modification landscape + m_zoneBuilder->actionLigoTile(dataZoneTemp, zonePosTemp); + } +} + + +void BuilderZoneRegion::reduceMin () +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); + sint32 i, j; + + sint32 newMinX = zoneRegion.getMinX(), newMinY = zoneRegion.getMinY (); + sint32 newMaxX = zoneRegion.getMaxX(), newMaxY = zoneRegion.getMaxY (); + bool bCanSuppr; + + // Reduce the MinY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMinY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinY; + else + break; + } + + // Reduce the MaxY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMaxY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxY; + else + break; + } + + // Reduce the MinX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMinX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinX; + else + break; + } + + // Reduce the MaxX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMaxX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + std::string str = zoneRegion.getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxX; + else + break; + } + + if ((newMinX != zoneRegion.getMinX ()) || + (newMinY != zoneRegion.getMinY ()) || + (newMaxX != zoneRegion.getMaxX ()) || + (newMaxY != zoneRegion.getMaxY ())) + { + resize(newMinX, newMaxX, newMinY, newMaxY); + } +} + +uint BuilderZoneRegion::getRegionId() const +{ + return m_regionId; +} + +void BuilderZoneRegion::resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + const NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->zoneRegion(m_regionId)->ligoZoneRegion(); + if ((zoneRegion.getMinX ()!= newMinX) || + (zoneRegion.getMaxX ()!= newMaxX) || + (zoneRegion.getMinY ()!= newMinY) || + (zoneRegion.getMaxY ()!= newMaxY)) + { + m_zoneBuilder->actionLigoResize(m_regionId, newMinX, newMaxX, newMinY, newMaxY); + } +} + +void BuilderZoneRegion::placePiece(sint32 x, sint32 y, uint8 rot, uint8 flip, + NLLIGO::SPiece &sMask, NLLIGO::SPiece &sPosX, NLLIGO::SPiece &sPosY, + const std::string &eltName) +{ + for (int j = 0; j < sMask.h; ++j) + for (int i = 0; i < sMask.w; ++i) + if (sMask.Tab[i + j * sMask.w]) + { + set(x + i, y + j, sPosX.Tab[i + j * sPosX.w], sPosY.Tab[i + j * sPosY.w], eltName); + setRot(x + i, y + j, rot); + setFlip(x + i, y + j, flip); + } +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h index 2170c67b9..fbc347ef0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/builder_zone_region.h @@ -1,107 +1,107 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef BUILDER_ZONE_REGION_H -#define BUILDER_ZONE_REGION_H - -// Project includes - -// NeL includes -#include -#include - -// STL includes -#include -#include -#include - -// Qt includes - -namespace LandscapeEditor -{ -class ZoneBuilder; -class ToUpdate; - -// CZoneRegion contains informations about the zones painted. -// (Legacy class from old world editor. It needs to refactoring!) -class BuilderZoneRegion -{ -public: - - explicit BuilderZoneRegion(uint regionId); - - // New interface - bool init(ZoneBuilder *zoneBuilder); - void add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); - void invertCutEdge(sint32 x, sint32 y, uint8 cePos); - void cycleTransition(sint32 x, sint32 y); - bool addNotPropagate(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); - - /// Brutal adding a zone over empty space do not propagate in any way -> can result - /// in inconsistency when trying the propagation mode - void addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); - void del(sint32 x, sint32 y, bool transition = false, ToUpdate *pUpdate = 0); - void move(sint32 x, sint32 y); - uint32 countZones(); - void reduceMin(); - uint getRegionId() const; - -private: - - // An element of the graph - struct SMatNode - { - std::string Name; - // Position in the tree (vector of nodes) - std::vector Arcs; - }; - - void addTransition(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); - - void addToUpdateAndCreate(BuilderZoneRegion *builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, - const std::string &newMat, ToUpdate *ptCreate, ToUpdate *ptUpdate); - - void putTransitions(sint32 x, sint32 y, const NLLIGO::SPiece &mask, const std::string &matName, ToUpdate *ptUpdate); - void updateTrans(sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement = 0); - - std::string getNextMatInTree(const std::string &matA, const std::string &matB); - - /// Find the fastest way between posA and posB in the MatTree (Dijkstra) - void tryPath(uint32 posA, uint32 posB, std::vector &path); - - void set(sint32 x, sint32 y, sint32 posX, sint32 posY, const std::string &zoneName, bool transition = false); - void setRot(sint32 x, sint32 y, uint8 rot); - void setFlip(sint32 x, sint32 y, uint8 flip); - void resize(sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); - - void placePiece(sint32 x, sint32 y, uint8 rot, uint8 flip, - NLLIGO::SPiece &sMask, NLLIGO::SPiece &sPosX, NLLIGO::SPiece &sPosY, - const std::string &eltName); - - uint m_regionId; - - // To use the global mask - ZoneBuilder *m_zoneBuilder; - - // The tree of transition between materials - std::vector m_matTree; - - bool m_firstInit; -}; - -} /* namespace LandscapeEditor */ - -#endif // BUILDER_ZONE_REGION_H +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef BUILDER_ZONE_REGION_H +#define BUILDER_ZONE_REGION_H + +// Project includes + +// NeL includes +#include +#include + +// STL includes +#include +#include +#include + +// Qt includes + +namespace LandscapeEditor +{ +class ZoneBuilder; +class ToUpdate; + +// CZoneRegion contains informations about the zones painted. +// (Legacy class from old world editor. It needs to refactoring!) +class BuilderZoneRegion +{ +public: + + explicit BuilderZoneRegion(uint regionId); + + // New interface + bool init(ZoneBuilder *zoneBuilder); + void add(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + void invertCutEdge(sint32 x, sint32 y, uint8 cePos); + void cycleTransition(sint32 x, sint32 y); + bool addNotPropagate(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + + /// Brutal adding a zone over empty space do not propagate in any way -> can result + /// in inconsistency when trying the propagation mode + void addForce (sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + void del(sint32 x, sint32 y, bool transition = false, ToUpdate *pUpdate = 0); + void move(sint32 x, sint32 y); + uint32 countZones(); + void reduceMin(); + uint getRegionId() const; + +private: + + // An element of the graph + struct SMatNode + { + std::string Name; + // Position in the tree (vector of nodes) + std::vector Arcs; + }; + + void addTransition(sint32 x, sint32 y, uint8 rot, uint8 flip, NLLIGO::CZoneBankElement *zoneBankElement); + + void addToUpdateAndCreate(BuilderZoneRegion *builderZoneRegion, sint32 sharePos, sint32 x, sint32 y, + const std::string &newMat, ToUpdate *ptCreate, ToUpdate *ptUpdate); + + void putTransitions(sint32 x, sint32 y, const NLLIGO::SPiece &mask, const std::string &matName, ToUpdate *ptUpdate); + void updateTrans(sint32 x, sint32 y, NLLIGO::CZoneBankElement *zoneBankElement = 0); + + std::string getNextMatInTree(const std::string &matA, const std::string &matB); + + /// Find the fastest way between posA and posB in the MatTree (Dijkstra) + void tryPath(uint32 posA, uint32 posB, std::vector &path); + + void set(sint32 x, sint32 y, sint32 posX, sint32 posY, const std::string &zoneName, bool transition = false); + void setRot(sint32 x, sint32 y, uint8 rot); + void setFlip(sint32 x, sint32 y, uint8 flip); + void resize(sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); + + void placePiece(sint32 x, sint32 y, uint8 rot, uint8 flip, + NLLIGO::SPiece &sMask, NLLIGO::SPiece &sPosX, NLLIGO::SPiece &sPosY, + const std::string &eltName); + + uint m_regionId; + + // To use the global mask + ZoneBuilder *m_zoneBuilder; + + // The tree of transition between materials + std::vector m_matTree; + + bool m_firstInit; +}; + +} /* namespace LandscapeEditor */ + +#endif // BUILDER_ZONE_REGION_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp index e5b3ad4d4..05b4d1671 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_actions.cpp @@ -1,178 +1,178 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_actions.h" -#include "builder_zone.h" - -// NeL includes -#include - -// Qt includes - -namespace LandscapeEditor -{ - -LigoTileCommand::LigoTileCommand(const LigoData &data, const ZonePosition &zonePos, - ZoneBuilder *zoneBuilder, LandscapeScene *scene, - QUndoCommand *parent) - : QUndoCommand(parent), - m_zoneBuilder(zoneBuilder), - m_scene(scene) -{ - // Backup position - m_zonePos = zonePos; - - // Backup new data - m_newLigoData = data; - - // Backup old data - m_zoneBuilder->ligoData(m_oldLigoData, m_zonePos); -} - -LigoTileCommand::~LigoTileCommand() -{ -} - -void LigoTileCommand::undo () -{ - m_zoneBuilder->setLigoData(m_oldLigoData, m_zonePos); -} - -void LigoTileCommand::redo () -{ - m_zoneBuilder->setLigoData(m_newLigoData, m_zonePos); -} - -UndoScanRegionCommand::UndoScanRegionCommand(bool direction, ZoneBuilder *zoneBuilder, LandscapeScene *scene, QUndoCommand *parent) - : QUndoCommand(parent), - m_direction(direction), - m_zoneBuilder(zoneBuilder), - m_scene(scene) -{ -} - -UndoScanRegionCommand::~UndoScanRegionCommand() -{ - m_zonePositionList.clear(); -} - -void UndoScanRegionCommand::setScanList(const QList &zonePositionList) -{ - m_zonePositionList = zonePositionList; -} - -void UndoScanRegionCommand::undo() -{ - if (m_direction) - applyChanges(); -} - -void UndoScanRegionCommand::redo() -{ - if (!m_direction) - applyChanges(); -} - -void UndoScanRegionCommand::applyChanges() -{ - for (int i = 0; i < m_zonePositionList.size(); ++i) - m_scene->deleteItemZone(m_zonePositionList.at(i)); - - for (int i = 0; i < m_zonePositionList.size(); ++i) - { - LigoData data; - m_zoneBuilder->ligoData(data, m_zonePositionList.at(i)); - m_scene->createItemZone(data, m_zonePositionList.at(i)); - } -} - -LigoResizeCommand::LigoResizeCommand(int index, sint32 newMinX, sint32 newMaxX, - sint32 newMinY, sint32 newMaxY, ZoneBuilder *zoneBuilder, - QUndoCommand *parent) - : QUndoCommand(parent), - m_zoneBuilder(zoneBuilder) -{ - m_index = index; - m_newMinX = newMinX; - m_newMaxX = newMaxX; - m_newMinY = newMinY; - m_newMaxY = newMaxY; - - // Backup old region zone - m_oldZoneRegion = m_zoneBuilder->zoneRegion(m_index)->ligoZoneRegion(); -} - -LigoResizeCommand::~LigoResizeCommand() -{ -} - -void LigoResizeCommand::undo () -{ - // Restore old region zone - m_zoneBuilder->zoneRegion(m_index)->setLigoZoneRegion(m_oldZoneRegion); -} - -void LigoResizeCommand::redo () -{ - // Get the zone region - NLLIGO::CZoneRegion ®ion = m_zoneBuilder->zoneRegion(m_index)->ligoZoneRegion(); - - sint32 i, j; - std::vector newZones; - newZones.resize((1 + m_newMaxX - m_newMinX) * (1 + m_newMaxY - m_newMinY)); - - sint32 newStride = 1 + m_newMaxX - m_newMinX; - sint32 Stride = 1 + region.getMaxX() - region.getMinX(); - - for (j = m_newMinY; j <= m_newMaxY; ++j) - for (i = m_newMinX; i <= m_newMaxX; ++i) - { - // Ref on the new value - LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; - - // In the old array ? - if ((i >= region.getMinX()) && (i <= region.getMaxX()) && - (j >= region.getMinY()) && (j <= region.getMaxY())) - { - // Backup values - m_zoneBuilder->ligoData(data, ZonePosition(i, j, m_index)); - } - } - region.resize(m_newMinX, m_newMaxX, m_newMinY, m_newMaxY); - - for (j = m_newMinY; j <= m_newMaxY; ++j) - for (i = m_newMinX; i <= m_newMaxX; ++i) - { - // Ref on the new value - const LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; - - region.setName(i, j, data.zoneName); - region.setPosX(i, j, data.posX); - region.setPosY(i, j, data.posY); - region.setRot(i, j, data.rot); - region.setFlip(i, j, data.flip); - uint k; - for (k = 0; k < 4; k++) - { - region.setSharingMatNames(i, j, k, data.sharingMatNames[k]); - region.setSharingCutEdges(i, j, k, data.sharingCutEdges[k]); - } - } -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_actions.h" +#include "builder_zone.h" + +// NeL includes +#include + +// Qt includes + +namespace LandscapeEditor +{ + +LigoTileCommand::LigoTileCommand(const LigoData &data, const ZonePosition &zonePos, + ZoneBuilder *zoneBuilder, LandscapeScene *scene, + QUndoCommand *parent) + : QUndoCommand(parent), + m_zoneBuilder(zoneBuilder), + m_scene(scene) +{ + // Backup position + m_zonePos = zonePos; + + // Backup new data + m_newLigoData = data; + + // Backup old data + m_zoneBuilder->ligoData(m_oldLigoData, m_zonePos); +} + +LigoTileCommand::~LigoTileCommand() +{ +} + +void LigoTileCommand::undo () +{ + m_zoneBuilder->setLigoData(m_oldLigoData, m_zonePos); +} + +void LigoTileCommand::redo () +{ + m_zoneBuilder->setLigoData(m_newLigoData, m_zonePos); +} + +UndoScanRegionCommand::UndoScanRegionCommand(bool direction, ZoneBuilder *zoneBuilder, LandscapeScene *scene, QUndoCommand *parent) + : QUndoCommand(parent), + m_direction(direction), + m_zoneBuilder(zoneBuilder), + m_scene(scene) +{ +} + +UndoScanRegionCommand::~UndoScanRegionCommand() +{ + m_zonePositionList.clear(); +} + +void UndoScanRegionCommand::setScanList(const QList &zonePositionList) +{ + m_zonePositionList = zonePositionList; +} + +void UndoScanRegionCommand::undo() +{ + if (m_direction) + applyChanges(); +} + +void UndoScanRegionCommand::redo() +{ + if (!m_direction) + applyChanges(); +} + +void UndoScanRegionCommand::applyChanges() +{ + for (int i = 0; i < m_zonePositionList.size(); ++i) + m_scene->deleteItemZone(m_zonePositionList.at(i)); + + for (int i = 0; i < m_zonePositionList.size(); ++i) + { + LigoData data; + m_zoneBuilder->ligoData(data, m_zonePositionList.at(i)); + m_scene->createItemZone(data, m_zonePositionList.at(i)); + } +} + +LigoResizeCommand::LigoResizeCommand(int index, sint32 newMinX, sint32 newMaxX, + sint32 newMinY, sint32 newMaxY, ZoneBuilder *zoneBuilder, + QUndoCommand *parent) + : QUndoCommand(parent), + m_zoneBuilder(zoneBuilder) +{ + m_index = index; + m_newMinX = newMinX; + m_newMaxX = newMaxX; + m_newMinY = newMinY; + m_newMaxY = newMaxY; + + // Backup old region zone + m_oldZoneRegion = m_zoneBuilder->zoneRegion(m_index)->ligoZoneRegion(); +} + +LigoResizeCommand::~LigoResizeCommand() +{ +} + +void LigoResizeCommand::undo () +{ + // Restore old region zone + m_zoneBuilder->zoneRegion(m_index)->setLigoZoneRegion(m_oldZoneRegion); +} + +void LigoResizeCommand::redo () +{ + // Get the zone region + NLLIGO::CZoneRegion ®ion = m_zoneBuilder->zoneRegion(m_index)->ligoZoneRegion(); + + sint32 i, j; + std::vector newZones; + newZones.resize((1 + m_newMaxX - m_newMinX) * (1 + m_newMaxY - m_newMinY)); + + sint32 newStride = 1 + m_newMaxX - m_newMinX; + sint32 Stride = 1 + region.getMaxX() - region.getMinX(); + + for (j = m_newMinY; j <= m_newMaxY; ++j) + for (i = m_newMinX; i <= m_newMaxX; ++i) + { + // Ref on the new value + LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; + + // In the old array ? + if ((i >= region.getMinX()) && (i <= region.getMaxX()) && + (j >= region.getMinY()) && (j <= region.getMaxY())) + { + // Backup values + m_zoneBuilder->ligoData(data, ZonePosition(i, j, m_index)); + } + } + region.resize(m_newMinX, m_newMaxX, m_newMinY, m_newMaxY); + + for (j = m_newMinY; j <= m_newMaxY; ++j) + for (i = m_newMinX; i <= m_newMaxX; ++i) + { + // Ref on the new value + const LigoData &data = newZones[(i - m_newMinX) + (j - m_newMinY) * newStride]; + + region.setName(i, j, data.zoneName); + region.setPosX(i, j, data.posX); + region.setPosY(i, j, data.posY); + region.setRot(i, j, data.rot); + region.setFlip(i, j, data.flip); + uint k; + for (k = 0; k < 4; k++) + { + region.setSharingMatNames(i, j, k, data.sharingMatNames[k]); + region.setSharingCutEdges(i, j, k, data.sharingCutEdges[k]); + } + } +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp index 17556d03f..73a6f5b25 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_plugin.cpp @@ -1,100 +1,100 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_editor_plugin.h" -#include "landscape_editor_window.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include "nel/misc/debug.h" - -// Qt includes -#include - -namespace LandscapeEditor -{ - -LandscapeEditorPlugin::~LandscapeEditorPlugin() -{ - Q_FOREACH(QObject *obj, m_autoReleaseObjects) - { - m_plugMan->removeObject(obj); - } - qDeleteAll(m_autoReleaseObjects); - m_autoReleaseObjects.clear(); -} - -bool LandscapeEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) -{ - Q_UNUSED(errorString); - m_plugMan = pluginManager; - - addAutoReleasedObject(new LandscapeEditorContext(this)); - return true; -} - -void LandscapeEditorPlugin::extensionsInitialized() -{ -} - -void LandscapeEditorPlugin::shutdown() -{ -} - -void LandscapeEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) -{ -#ifdef NL_OS_WINDOWS - // Ensure that a context doesn't exist yet. - // This only applies to platforms without PIC, e.g. Windows. - nlassert(!NLMISC::INelContext::isContextInitialised()); -#endif // NL_OS_WINDOWS - m_libContext = new NLMISC::CLibraryContext(*nelContext); -} - -void LandscapeEditorPlugin::addAutoReleasedObject(QObject *obj) -{ - m_plugMan->addObject(obj); - m_autoReleaseObjects.prepend(obj); -} - -LandscapeEditorContext::LandscapeEditorContext(QObject *parent) - : IContext(parent), - m_landEditorWindow(0) -{ - m_landEditorWindow = new LandscapeEditorWindow(); -} - -QUndoStack *LandscapeEditorContext::undoStack() -{ - return m_landEditorWindow->undoStack(); -} - -void LandscapeEditorContext::open() -{ - m_landEditorWindow->open(); -} - -QWidget *LandscapeEditorContext::widget() -{ - return m_landEditorWindow; -} - -} -Q_EXPORT_PLUGIN(LandscapeEditor::LandscapeEditorPlugin) +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_editor_plugin.h" +#include "landscape_editor_window.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include "nel/misc/debug.h" + +// Qt includes +#include + +namespace LandscapeEditor +{ + +LandscapeEditorPlugin::~LandscapeEditorPlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); +} + +bool LandscapeEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + Q_UNUSED(errorString); + m_plugMan = pluginManager; + + addAutoReleasedObject(new LandscapeEditorContext(this)); + return true; +} + +void LandscapeEditorPlugin::extensionsInitialized() +{ +} + +void LandscapeEditorPlugin::shutdown() +{ +} + +void LandscapeEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_libContext = new NLMISC::CLibraryContext(*nelContext); +} + +void LandscapeEditorPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +LandscapeEditorContext::LandscapeEditorContext(QObject *parent) + : IContext(parent), + m_landEditorWindow(0) +{ + m_landEditorWindow = new LandscapeEditorWindow(); +} + +QUndoStack *LandscapeEditorContext::undoStack() +{ + return m_landEditorWindow->undoStack(); +} + +void LandscapeEditorContext::open() +{ + m_landEditorWindow->open(); +} + +QWidget *LandscapeEditorContext::widget() +{ + return m_landEditorWindow; +} + +} +Q_EXPORT_PLUGIN(LandscapeEditor::LandscapeEditorPlugin) diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp index 22598c555..3f0ae5874 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_editor_window.cpp @@ -1,414 +1,414 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_editor_window.h" -#include "landscape_editor_constants.h" -#include "builder_zone.h" -#include "zone_region_editor.h" -#include "landscape_scene.h" -#include "project_settings_dialog.h" -#include "snapshot_dialog.h" - -#include "../core/icore.h" -#include "../core/menu_manager.h" -#include "../core/core_constants.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include -#include - -namespace LandscapeEditor -{ - -static const int LANDSCAPE_ID = 32; -int NewLandCounter = 0; -QString _lastDir; - -LandscapeEditorWindow::LandscapeEditorWindow(QWidget *parent) - : QMainWindow(parent), - m_currentItem(0), - m_landscapeScene(0), - m_zoneBuilder(0), - m_undoStack(0), - m_oglWidget(0) -{ - m_ui.setupUi(this); - - m_undoStack = new QUndoStack(this); - m_landscapeScene = new LandscapeScene(160, this); - - m_zoneBuilder = new ZoneBuilder(m_landscapeScene, m_ui.zoneListWidget, m_undoStack); - m_ui.zoneListWidget->setZoneBuilder(m_zoneBuilder); - m_ui.zoneListWidget->updateUi(); - - m_landscapeScene->setZoneBuilder(m_zoneBuilder); - m_ui.graphicsView->setScene(m_landscapeScene); - - m_ui.newLandAction->setIcon(QIcon(Core::Constants::ICON_NEW)); - m_ui.saveAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); - m_ui.saveLandAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); - m_ui.saveAsLandAction->setIcon(QIcon(Core::Constants::ICON_SAVE_AS)); - m_ui.zonesDockWidget->toggleViewAction()->setIcon(QIcon(Constants::ICON_LANDSCAPE_ZONES)); - m_ui.landscapesDockWidget->toggleViewAction()->setIcon(QIcon(Constants::ICON_ZONE_ITEM)); - - m_ui.deleteLandAction->setEnabled(false); - - createMenus(); - createToolBars(); - readSettings(); - - connect(m_ui.saveAction, SIGNAL(triggered()), this, SLOT(save())); - connect(m_ui.projectSettingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings())); - connect(m_ui.snapshotAction, SIGNAL(triggered()), this, SLOT(openSnapshotDialog())); - connect(m_ui.enableGridAction, SIGNAL(toggled(bool)), m_ui.graphicsView, SLOT(setVisibleGrid(bool))); - - connect(m_ui.newLandAction, SIGNAL(triggered()), this, SLOT(newLand())); - connect(m_ui.setActiveLandAction, SIGNAL(triggered()), this, SLOT(setActiveLand())); - connect(m_ui.saveLandAction, SIGNAL(triggered()), this, SLOT(saveSelectedLand())); - connect(m_ui.saveAsLandAction, SIGNAL(triggered()), this, SLOT(saveAsSelectedLand())); - connect(m_ui.deleteLandAction, SIGNAL(triggered()), this, SLOT(deleteSelectedLand())); - connect(m_ui.transitionModeAction, SIGNAL(toggled(bool)), m_landscapeScene, SLOT(setTransitionMode(bool))); - - connect(m_ui.landscapesListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenu())); - m_ui.landscapesListWidget->setContextMenuPolicy(Qt::CustomContextMenu); - - m_statusBarTimer = new QTimer(this); - connect(m_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); - - m_statusInfo = new QLabel(this); - m_statusInfo->hide(); - Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(m_statusInfo); -} - -LandscapeEditorWindow::~LandscapeEditorWindow() -{ - writeSettings(); - delete m_zoneBuilder; -} - -QUndoStack *LandscapeEditorWindow::undoStack() const -{ - return m_undoStack; -} - -void LandscapeEditorWindow::open() -{ - QStringList fileNames = QFileDialog::getOpenFileNames(this, - tr("Open NeL Ligo land file"), _lastDir, - tr("All NeL Ligo land files (*.land)")); - - setCursor(Qt::WaitCursor); - if (!fileNames.isEmpty()) - { - QStringList list = fileNames; - _lastDir = QFileInfo(list.front()).absolutePath(); - Q_FOREACH(QString fileName, fileNames) - { - int row = createLandscape(fileName); - if (row != -1) - setActiveLandscape(row); - } - } - setCursor(Qt::ArrowCursor); -} - -void LandscapeEditorWindow::save() -{ - saveLandscape(m_ui.landscapesListWidget->row(m_currentItem), true); -} - -void LandscapeEditorWindow::openProjectSettings() -{ - ProjectSettingsDialog *dialog = new ProjectSettingsDialog(m_zoneBuilder->dataPath(), this); - dialog->show(); - int ok = dialog->exec(); - if (ok == QDialog::Accepted) - { - m_zoneBuilder->init(dialog->dataPath(), true); - m_ui.zoneListWidget->updateUi(); - } - delete dialog; -} - -void LandscapeEditorWindow::openSnapshotDialog() -{ - SnapshotDialog *dialog = new SnapshotDialog(this); - dialog->show(); - int ok = dialog->exec(); - if (ok == QDialog::Accepted) - { - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save screenshot landscape"), _lastDir, - tr("Image file (*.png)")); - - setCursor(Qt::WaitCursor); - - NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->currentZoneRegion()->ligoZoneRegion(); - sint32 regionMinX = zoneRegion.getMinX(); - sint32 regionMaxX = zoneRegion.getMaxX(); - sint32 regionMinY = zoneRegion.getMinY(); - sint32 regionMaxY = zoneRegion.getMaxY(); - - int regionWidth = (regionMaxX - regionMinX + 1); - int regionHeight = (regionMaxY - regionMinY + 1); - - int cellSize = m_landscapeScene->cellSize(); - QRectF rect(regionMinX * cellSize, abs(regionMaxY) * cellSize, regionWidth * cellSize, regionHeight * cellSize); - - if (dialog->isCustomSize()) - { - int widthSnapshot = dialog->widthSnapshot(); - int heightSnapshot = dialog->heightSnapshot(); - if (dialog->isKeepRatio()) - heightSnapshot = (widthSnapshot / regionWidth) * regionHeight; - - m_landscapeScene->snapshot(fileName, widthSnapshot, heightSnapshot, rect); - } - else - { - m_landscapeScene->snapshot(fileName, regionWidth * dialog->resolutionZone(), - regionHeight * dialog->resolutionZone(), rect); - } - setCursor(Qt::ArrowCursor); - } - delete dialog; -} - -void LandscapeEditorWindow::customContextMenu() -{ - if (m_ui.landscapesListWidget->currentRow() == -1) - return; - QMenu *popurMenu = new QMenu(this); - popurMenu->addAction(m_ui.setActiveLandAction); - popurMenu->addAction(m_ui.saveLandAction); - popurMenu->addAction(m_ui.saveAsLandAction); - popurMenu->addAction(m_ui.deleteLandAction); - popurMenu->exec(QCursor::pos()); - delete popurMenu; -} - -void LandscapeEditorWindow::newLand() -{ - int row = createLandscape(QString()); - if (row != -1) - setActiveLandscape(row); -} - -void LandscapeEditorWindow::setActiveLand() -{ - setActiveLandscape(m_ui.landscapesListWidget->currentRow()); -} - -void LandscapeEditorWindow::saveSelectedLand() -{ - saveLandscape(m_ui.landscapesListWidget->currentRow(), true); -} - -void LandscapeEditorWindow::saveAsSelectedLand() -{ - saveLandscape(m_ui.landscapesListWidget->currentRow(), false); -} - -void LandscapeEditorWindow::deleteSelectedLand() -{ - int row = m_ui.landscapesListWidget->currentRow(); - int current_row = m_ui.landscapesListWidget->row(m_currentItem); - QListWidgetItem *item = m_ui.landscapesListWidget->item(row); - if (row == current_row) - { - if (row == 0) - ++row; - else - --row; - setActiveLandscape(row); - } - m_zoneBuilder->deleteZoneRegion(item->data(LANDSCAPE_ID).toInt()); - m_ui.landscapesListWidget->removeItemWidget(item); - delete item; - - if (m_ui.landscapesListWidget->count() == 1) - m_ui.deleteLandAction->setEnabled(false); - - m_undoStack->clear(); -} - -int LandscapeEditorWindow::createLandscape(const QString &fileName) -{ - int id; - if (fileName.isEmpty()) - id = m_zoneBuilder->createZoneRegion(); - else - id = m_zoneBuilder->createZoneRegion(fileName); - - if (id == -1) - { - QMessageBox::critical(this, "Landscape Editor", tr("Cannot add this zone because it overlaps existing ones")); - return -1; - } - ZoneRegionObject *zoneRegion = m_zoneBuilder->zoneRegion(id); - m_ui.graphicsView->setCenter(QPointF(zoneRegion->ligoZoneRegion().getMinX() * m_landscapeScene->cellSize(), - abs(zoneRegion->ligoZoneRegion().getMinY()) * m_landscapeScene->cellSize())); - - QListWidgetItem *item; - if (fileName.isEmpty()) - item = new QListWidgetItem(QString("NewLandscape%1").arg(NewLandCounter++), m_ui.landscapesListWidget); - else - item = new QListWidgetItem(fileName, m_ui.landscapesListWidget); - - item->setData(LANDSCAPE_ID, id); - item->setFont(QFont("SansSerif", 9, QFont::Normal)); - - if (m_ui.landscapesListWidget->count() > 1) - m_ui.deleteLandAction->setEnabled(true); - - return m_ui.landscapesListWidget->count() - 1; -} - -void LandscapeEditorWindow::setActiveLandscape(int row) -{ - if ((0 <= row) && (row < m_ui.landscapesListWidget->count())) - { - if (m_currentItem != 0) - m_currentItem->setFont(QFont("SansSerif", 9, QFont::Normal)); - - QListWidgetItem *item = m_ui.landscapesListWidget->item(row); - item->setFont(QFont("SansSerif", 9, QFont::Bold)); - m_zoneBuilder->setCurrentZoneRegion(item->data(LANDSCAPE_ID).toInt()); - m_currentItem = item; - } -} - -void LandscapeEditorWindow::saveLandscape(int row, bool force) -{ - if ((0 <= row) && (row < m_ui.landscapesListWidget->count())) - { - QListWidgetItem *item = m_ui.landscapesListWidget->item(row); - ZoneRegionObject *regionObject = m_zoneBuilder->zoneRegion(item->data(LANDSCAPE_ID).toInt()); - if ((!force) || (regionObject->fileName().empty())) - { - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save NeL Ligo land file"), _lastDir, - tr("NeL Ligo land file (*.land)")); - if (!fileName.isEmpty()) - { - regionObject->setFileName(fileName.toStdString()); - regionObject->save(); - regionObject->setModified(false); - item->setText(fileName); - } - } - else - { - regionObject->save(); - regionObject->setModified(false); - } - } -} - -void LandscapeEditorWindow::showEvent(QShowEvent *showEvent) -{ - QMainWindow::showEvent(showEvent); - if (m_oglWidget != 0) - m_oglWidget->makeCurrent(); - m_statusInfo->show(); - m_statusBarTimer->start(100); -} - -void LandscapeEditorWindow::hideEvent(QHideEvent *hideEvent) -{ - QMainWindow::hideEvent(hideEvent); - m_statusInfo->hide(); - m_statusBarTimer->stop(); -} - -void LandscapeEditorWindow::updateStatusBar() -{ - m_statusInfo->setText(m_landscapeScene->zoneNameFromMousePos()); -} - -void LandscapeEditorWindow::createMenus() -{ - Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); -} - -void LandscapeEditorWindow::createToolBars() -{ - Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); - //QAction *action = menuManager->action(Core::Constants::NEW); - //m_ui.fileToolBar->addAction(action); - //action = menuManager->action(Core::Constants::SAVE); - //m_ui.fileToolBar->addAction(action); - //action = menuManager->action(Core::Constants::SAVE_AS); - //m_ui.fileToolBar->addAction(action); - - QAction *action = menuManager->action(Core::Constants::OPEN); - m_ui.fileToolBar->addAction(m_ui.newLandAction); - m_ui.fileToolBar->addAction(action); - m_ui.fileToolBar->addAction(m_ui.saveAction); - m_ui.fileToolBar->addSeparator(); - - action = menuManager->action(Core::Constants::UNDO); - if (action != 0) - m_ui.fileToolBar->addAction(action); - - action = menuManager->action(Core::Constants::REDO); - if (action != 0) - m_ui.fileToolBar->addAction(action); - - m_ui.zoneToolBar->insertAction(m_ui.enableGridAction, m_ui.landscapesDockWidget->toggleViewAction()); - m_ui.zoneToolBar->insertAction(m_ui.enableGridAction, m_ui.zonesDockWidget->toggleViewAction()); -} - -void LandscapeEditorWindow::readSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Constants::LANDSCAPE_EDITOR_SECTION); - restoreState(settings->value(Constants::LANDSCAPE_WINDOW_STATE).toByteArray()); - restoreGeometry(settings->value(Constants::LANDSCAPE_WINDOW_GEOMETRY).toByteArray()); - - // Read landscape data directory (contains sub-paths: zone logos, zone bitmaps) - m_zoneBuilder->init(settings->value(Constants::LANDSCAPE_DATA_DIRECTORY).toString()); - m_ui.zoneListWidget->updateUi(); - - // Use OpenGL graphics system instead raster graphics system - if (settings->value(Constants::LANDSCAPE_USE_OPENGL, false).toBool()) - { - m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer)); - m_ui.graphicsView->setViewport(m_oglWidget); - } - - settings->endGroup(); -} - -void LandscapeEditorWindow::writeSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Constants::LANDSCAPE_EDITOR_SECTION); - settings->setValue(Constants::LANDSCAPE_WINDOW_STATE, saveState()); - settings->setValue(Constants::LANDSCAPE_WINDOW_GEOMETRY, saveGeometry()); - settings->setValue(Constants::LANDSCAPE_DATA_DIRECTORY, m_zoneBuilder->dataPath()); - settings->endGroup(); - settings->sync(); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_editor_window.h" +#include "landscape_editor_constants.h" +#include "builder_zone.h" +#include "zone_region_editor.h" +#include "landscape_scene.h" +#include "project_settings_dialog.h" +#include "snapshot_dialog.h" + +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include + +namespace LandscapeEditor +{ + +static const int LANDSCAPE_ID = 32; +int NewLandCounter = 0; +QString _lastDir; + +LandscapeEditorWindow::LandscapeEditorWindow(QWidget *parent) + : QMainWindow(parent), + m_currentItem(0), + m_landscapeScene(0), + m_zoneBuilder(0), + m_undoStack(0), + m_oglWidget(0) +{ + m_ui.setupUi(this); + + m_undoStack = new QUndoStack(this); + m_landscapeScene = new LandscapeScene(160, this); + + m_zoneBuilder = new ZoneBuilder(m_landscapeScene, m_ui.zoneListWidget, m_undoStack); + m_ui.zoneListWidget->setZoneBuilder(m_zoneBuilder); + m_ui.zoneListWidget->updateUi(); + + m_landscapeScene->setZoneBuilder(m_zoneBuilder); + m_ui.graphicsView->setScene(m_landscapeScene); + + m_ui.newLandAction->setIcon(QIcon(Core::Constants::ICON_NEW)); + m_ui.saveAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); + m_ui.saveLandAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); + m_ui.saveAsLandAction->setIcon(QIcon(Core::Constants::ICON_SAVE_AS)); + m_ui.zonesDockWidget->toggleViewAction()->setIcon(QIcon(Constants::ICON_LANDSCAPE_ZONES)); + m_ui.landscapesDockWidget->toggleViewAction()->setIcon(QIcon(Constants::ICON_ZONE_ITEM)); + + m_ui.deleteLandAction->setEnabled(false); + + createMenus(); + createToolBars(); + readSettings(); + + connect(m_ui.saveAction, SIGNAL(triggered()), this, SLOT(save())); + connect(m_ui.projectSettingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings())); + connect(m_ui.snapshotAction, SIGNAL(triggered()), this, SLOT(openSnapshotDialog())); + connect(m_ui.enableGridAction, SIGNAL(toggled(bool)), m_ui.graphicsView, SLOT(setVisibleGrid(bool))); + + connect(m_ui.newLandAction, SIGNAL(triggered()), this, SLOT(newLand())); + connect(m_ui.setActiveLandAction, SIGNAL(triggered()), this, SLOT(setActiveLand())); + connect(m_ui.saveLandAction, SIGNAL(triggered()), this, SLOT(saveSelectedLand())); + connect(m_ui.saveAsLandAction, SIGNAL(triggered()), this, SLOT(saveAsSelectedLand())); + connect(m_ui.deleteLandAction, SIGNAL(triggered()), this, SLOT(deleteSelectedLand())); + connect(m_ui.transitionModeAction, SIGNAL(toggled(bool)), m_landscapeScene, SLOT(setTransitionMode(bool))); + + connect(m_ui.landscapesListWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(customContextMenu())); + m_ui.landscapesListWidget->setContextMenuPolicy(Qt::CustomContextMenu); + + m_statusBarTimer = new QTimer(this); + connect(m_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); + + m_statusInfo = new QLabel(this); + m_statusInfo->hide(); + Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(m_statusInfo); +} + +LandscapeEditorWindow::~LandscapeEditorWindow() +{ + writeSettings(); + delete m_zoneBuilder; +} + +QUndoStack *LandscapeEditorWindow::undoStack() const +{ + return m_undoStack; +} + +void LandscapeEditorWindow::open() +{ + QStringList fileNames = QFileDialog::getOpenFileNames(this, + tr("Open NeL Ligo land file"), _lastDir, + tr("All NeL Ligo land files (*.land)")); + + setCursor(Qt::WaitCursor); + if (!fileNames.isEmpty()) + { + QStringList list = fileNames; + _lastDir = QFileInfo(list.front()).absolutePath(); + Q_FOREACH(QString fileName, fileNames) + { + int row = createLandscape(fileName); + if (row != -1) + setActiveLandscape(row); + } + } + setCursor(Qt::ArrowCursor); +} + +void LandscapeEditorWindow::save() +{ + saveLandscape(m_ui.landscapesListWidget->row(m_currentItem), true); +} + +void LandscapeEditorWindow::openProjectSettings() +{ + ProjectSettingsDialog *dialog = new ProjectSettingsDialog(m_zoneBuilder->dataPath(), this); + dialog->show(); + int ok = dialog->exec(); + if (ok == QDialog::Accepted) + { + m_zoneBuilder->init(dialog->dataPath(), true); + m_ui.zoneListWidget->updateUi(); + } + delete dialog; +} + +void LandscapeEditorWindow::openSnapshotDialog() +{ + SnapshotDialog *dialog = new SnapshotDialog(this); + dialog->show(); + int ok = dialog->exec(); + if (ok == QDialog::Accepted) + { + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save screenshot landscape"), _lastDir, + tr("Image file (*.png)")); + + setCursor(Qt::WaitCursor); + + NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->currentZoneRegion()->ligoZoneRegion(); + sint32 regionMinX = zoneRegion.getMinX(); + sint32 regionMaxX = zoneRegion.getMaxX(); + sint32 regionMinY = zoneRegion.getMinY(); + sint32 regionMaxY = zoneRegion.getMaxY(); + + int regionWidth = (regionMaxX - regionMinX + 1); + int regionHeight = (regionMaxY - regionMinY + 1); + + int cellSize = m_landscapeScene->cellSize(); + QRectF rect(regionMinX * cellSize, abs(regionMaxY) * cellSize, regionWidth * cellSize, regionHeight * cellSize); + + if (dialog->isCustomSize()) + { + int widthSnapshot = dialog->widthSnapshot(); + int heightSnapshot = dialog->heightSnapshot(); + if (dialog->isKeepRatio()) + heightSnapshot = (widthSnapshot / regionWidth) * regionHeight; + + m_landscapeScene->snapshot(fileName, widthSnapshot, heightSnapshot, rect); + } + else + { + m_landscapeScene->snapshot(fileName, regionWidth * dialog->resolutionZone(), + regionHeight * dialog->resolutionZone(), rect); + } + setCursor(Qt::ArrowCursor); + } + delete dialog; +} + +void LandscapeEditorWindow::customContextMenu() +{ + if (m_ui.landscapesListWidget->currentRow() == -1) + return; + QMenu *popurMenu = new QMenu(this); + popurMenu->addAction(m_ui.setActiveLandAction); + popurMenu->addAction(m_ui.saveLandAction); + popurMenu->addAction(m_ui.saveAsLandAction); + popurMenu->addAction(m_ui.deleteLandAction); + popurMenu->exec(QCursor::pos()); + delete popurMenu; +} + +void LandscapeEditorWindow::newLand() +{ + int row = createLandscape(QString()); + if (row != -1) + setActiveLandscape(row); +} + +void LandscapeEditorWindow::setActiveLand() +{ + setActiveLandscape(m_ui.landscapesListWidget->currentRow()); +} + +void LandscapeEditorWindow::saveSelectedLand() +{ + saveLandscape(m_ui.landscapesListWidget->currentRow(), true); +} + +void LandscapeEditorWindow::saveAsSelectedLand() +{ + saveLandscape(m_ui.landscapesListWidget->currentRow(), false); +} + +void LandscapeEditorWindow::deleteSelectedLand() +{ + int row = m_ui.landscapesListWidget->currentRow(); + int current_row = m_ui.landscapesListWidget->row(m_currentItem); + QListWidgetItem *item = m_ui.landscapesListWidget->item(row); + if (row == current_row) + { + if (row == 0) + ++row; + else + --row; + setActiveLandscape(row); + } + m_zoneBuilder->deleteZoneRegion(item->data(LANDSCAPE_ID).toInt()); + m_ui.landscapesListWidget->removeItemWidget(item); + delete item; + + if (m_ui.landscapesListWidget->count() == 1) + m_ui.deleteLandAction->setEnabled(false); + + m_undoStack->clear(); +} + +int LandscapeEditorWindow::createLandscape(const QString &fileName) +{ + int id; + if (fileName.isEmpty()) + id = m_zoneBuilder->createZoneRegion(); + else + id = m_zoneBuilder->createZoneRegion(fileName); + + if (id == -1) + { + QMessageBox::critical(this, "Landscape Editor", tr("Cannot add this zone because it overlaps existing ones")); + return -1; + } + ZoneRegionObject *zoneRegion = m_zoneBuilder->zoneRegion(id); + m_ui.graphicsView->setCenter(QPointF(zoneRegion->ligoZoneRegion().getMinX() * m_landscapeScene->cellSize(), + abs(zoneRegion->ligoZoneRegion().getMinY()) * m_landscapeScene->cellSize())); + + QListWidgetItem *item; + if (fileName.isEmpty()) + item = new QListWidgetItem(QString("NewLandscape%1").arg(NewLandCounter++), m_ui.landscapesListWidget); + else + item = new QListWidgetItem(fileName, m_ui.landscapesListWidget); + + item->setData(LANDSCAPE_ID, id); + item->setFont(QFont("SansSerif", 9, QFont::Normal)); + + if (m_ui.landscapesListWidget->count() > 1) + m_ui.deleteLandAction->setEnabled(true); + + return m_ui.landscapesListWidget->count() - 1; +} + +void LandscapeEditorWindow::setActiveLandscape(int row) +{ + if ((0 <= row) && (row < m_ui.landscapesListWidget->count())) + { + if (m_currentItem != 0) + m_currentItem->setFont(QFont("SansSerif", 9, QFont::Normal)); + + QListWidgetItem *item = m_ui.landscapesListWidget->item(row); + item->setFont(QFont("SansSerif", 9, QFont::Bold)); + m_zoneBuilder->setCurrentZoneRegion(item->data(LANDSCAPE_ID).toInt()); + m_currentItem = item; + } +} + +void LandscapeEditorWindow::saveLandscape(int row, bool force) +{ + if ((0 <= row) && (row < m_ui.landscapesListWidget->count())) + { + QListWidgetItem *item = m_ui.landscapesListWidget->item(row); + ZoneRegionObject *regionObject = m_zoneBuilder->zoneRegion(item->data(LANDSCAPE_ID).toInt()); + if ((!force) || (regionObject->fileName().empty())) + { + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save NeL Ligo land file"), _lastDir, + tr("NeL Ligo land file (*.land)")); + if (!fileName.isEmpty()) + { + regionObject->setFileName(fileName.toStdString()); + regionObject->save(); + regionObject->setModified(false); + item->setText(fileName); + } + } + else + { + regionObject->save(); + regionObject->setModified(false); + } + } +} + +void LandscapeEditorWindow::showEvent(QShowEvent *showEvent) +{ + QMainWindow::showEvent(showEvent); + if (m_oglWidget != 0) + m_oglWidget->makeCurrent(); + m_statusInfo->show(); + m_statusBarTimer->start(100); +} + +void LandscapeEditorWindow::hideEvent(QHideEvent *hideEvent) +{ + QMainWindow::hideEvent(hideEvent); + m_statusInfo->hide(); + m_statusBarTimer->stop(); +} + +void LandscapeEditorWindow::updateStatusBar() +{ + m_statusInfo->setText(m_landscapeScene->zoneNameFromMousePos()); +} + +void LandscapeEditorWindow::createMenus() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); +} + +void LandscapeEditorWindow::createToolBars() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + //QAction *action = menuManager->action(Core::Constants::NEW); + //m_ui.fileToolBar->addAction(action); + //action = menuManager->action(Core::Constants::SAVE); + //m_ui.fileToolBar->addAction(action); + //action = menuManager->action(Core::Constants::SAVE_AS); + //m_ui.fileToolBar->addAction(action); + + QAction *action = menuManager->action(Core::Constants::OPEN); + m_ui.fileToolBar->addAction(m_ui.newLandAction); + m_ui.fileToolBar->addAction(action); + m_ui.fileToolBar->addAction(m_ui.saveAction); + m_ui.fileToolBar->addSeparator(); + + action = menuManager->action(Core::Constants::UNDO); + if (action != 0) + m_ui.fileToolBar->addAction(action); + + action = menuManager->action(Core::Constants::REDO); + if (action != 0) + m_ui.fileToolBar->addAction(action); + + m_ui.zoneToolBar->insertAction(m_ui.enableGridAction, m_ui.landscapesDockWidget->toggleViewAction()); + m_ui.zoneToolBar->insertAction(m_ui.enableGridAction, m_ui.zonesDockWidget->toggleViewAction()); +} + +void LandscapeEditorWindow::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::LANDSCAPE_EDITOR_SECTION); + restoreState(settings->value(Constants::LANDSCAPE_WINDOW_STATE).toByteArray()); + restoreGeometry(settings->value(Constants::LANDSCAPE_WINDOW_GEOMETRY).toByteArray()); + + // Read landscape data directory (contains sub-paths: zone logos, zone bitmaps) + m_zoneBuilder->init(settings->value(Constants::LANDSCAPE_DATA_DIRECTORY).toString()); + m_ui.zoneListWidget->updateUi(); + + // Use OpenGL graphics system instead raster graphics system + if (settings->value(Constants::LANDSCAPE_USE_OPENGL, false).toBool()) + { + m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer)); + m_ui.graphicsView->setViewport(m_oglWidget); + } + + settings->endGroup(); +} + +void LandscapeEditorWindow::writeSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::LANDSCAPE_EDITOR_SECTION); + settings->setValue(Constants::LANDSCAPE_WINDOW_STATE, saveState()); + settings->setValue(Constants::LANDSCAPE_WINDOW_GEOMETRY, saveGeometry()); + settings->setValue(Constants::LANDSCAPE_DATA_DIRECTORY, m_zoneBuilder->dataPath()); + settings->endGroup(); + settings->sync(); +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp index 0018b4a53..1b9aaa9dc 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene.cpp @@ -1,498 +1,498 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_scene.h" -#include "pixmap_database.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include - -namespace LandscapeEditor -{ - -static const int ZONE_NAME = 0; -static const int LAYER_ZONES = 2; -static const int LAYER_EMPTY_ZONES = 3; -static const int LAYER_BLACKOUT = 4; -const char *const LAYER_BLACKOUT_NAME = "blackout"; - -const int MAX_SCENE_WIDTH = 256; -const int MAX_SCENE_HEIGHT = 256; - -LandscapeScene::LandscapeScene(int sizeCell, QObject *parent) - : QGraphicsScene(parent), - m_cellSize(sizeCell), - m_transitionMode(false), - m_mouseButton(Qt::NoButton), - m_zoneBuilder(0) -{ - setSceneRect(QRectF(0, m_cellSize, MAX_SCENE_WIDTH * m_cellSize, MAX_SCENE_HEIGHT * m_cellSize)); -} - -LandscapeScene::~LandscapeScene() -{ -} - -int LandscapeScene::cellSize() const -{ - return m_cellSize; -} - -void LandscapeScene::setZoneBuilder(ZoneBuilder *zoneBuilder) -{ - m_zoneBuilder = zoneBuilder; -} - -QGraphicsItem *LandscapeScene::createItemZone(const LigoData &data, const ZonePosition &zonePos) -{ - if ((data.zoneName == STRING_OUT_OF_BOUND) || (checkUnderZone(zonePos.x, zonePos.y))) - return 0; - - if (data.zoneName == STRING_UNUSED) - return createItemEmptyZone(zonePos); - - if ((m_zoneBuilder == 0) || (data.zoneName.empty())) - return 0; - - // Get image from pixmap database - QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(data.zoneName.c_str())); - if (pixmap == 0) - return 0; - - // Rotate the image counterclockwise - QMatrix matrix; - matrix.rotate(-data.rot * 90.0); - - QGraphicsPixmapItem *item; - - if (data.flip == 0) - { - item = addPixmap(pixmap->transformed(matrix, Qt::SmoothTransformation)); - } - else - { - // mirror image - QImage mirrorImage = pixmap->toImage(); - QPixmap mirrorPixmap = QPixmap::fromImage(mirrorImage.mirrored(true, false)); - item = addPixmap(mirrorPixmap.transformed(matrix, Qt::SmoothTransformation)); - } - // Enable bilinear filtering - item->setTransformationMode(Qt::SmoothTransformation); - - sint32 sizeX = 1, sizeY = 1; - sizeX = float(pixmap->width()) / m_zoneBuilder->pixmapDatabase()->textureSize(); - sizeY = float(pixmap->width()) / m_zoneBuilder->pixmapDatabase()->textureSize(); - - sint32 deltaX = 0, deltaY = 0; - - // Calculate offset for graphics item (for items with size that are larger than 1) - if ((sizeX > 1) || (sizeY > 1)) - { - if (data.flip == 0) - { - switch (data.rot) - { - case 0: - deltaX = -data.posX; - deltaY = -data.posY + sizeY - 1; - break; - case 1: - deltaX = -(sizeY - 1 - data.posY); - deltaY = -data.posX + sizeX - 1; - break; - case 2: - deltaX = -(sizeX - 1 - data.posX); - deltaY = data.posY; - break; - case 3: - deltaX = -data.posY; - deltaY = data.posX; - break; - } - } - else - { - switch (data.rot) - { - case 0: - deltaX = -(sizeX - 1 - data.posX); - deltaY = -data.posY + sizeY - 1; - break; - case 1: - deltaX = -(sizeY - 1 - data.posY); - deltaY = +data.posX; - break; - case 2: - deltaX = -data.posX; - deltaY = data.posY; - break; - case 3: - deltaX = -data.posY; - deltaY = -data.posX + sizeX - 1; - break; - } - } - } - - // Set position graphics item with offset for large piece - item->setPos((zonePos.x + deltaX) * m_cellSize, (abs(int(zonePos.y + deltaY))) * m_cellSize); - - // The size graphics item should be equal or proportional m_cellSize - item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); - - item->setData(ZONE_NAME, QString(data.zoneName.c_str())); - - // for not full item zone - item->setZValue(LAYER_ZONES); - - item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); - - return item; -} - -QGraphicsItem *LandscapeScene::createItemEmptyZone(const ZonePosition &zonePos) -{ - if (m_zoneBuilder == 0) - return 0; - - if (checkUnderZone(zonePos.x, zonePos.y)) - return 0; - - // Get image from pixmap database - QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(STRING_UNUSED)); - - if (pixmap == 0) - return 0; - - QGraphicsPixmapItem *item = addPixmap(*pixmap); - - // Enable bilinear filtering - item->setTransformationMode(Qt::SmoothTransformation); - - // Set position graphics item - item->setPos(zonePos.x * m_cellSize, abs(int(zonePos.y)) * m_cellSize); - - // The size graphics item should be equal or proportional m_cellSize - item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); - - // for not full item zone - item->setZValue(LAYER_EMPTY_ZONES); - - item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); - - return item; -} - -QGraphicsRectItem *LandscapeScene::createLayerBlackout(const NLLIGO::CZoneRegion &zoneRegion) -{ - QGraphicsRectItem *rectItem = addRect(zoneRegion.getMinX() * m_cellSize, - abs(zoneRegion.getMaxY()) * m_cellSize, - (abs(zoneRegion.getMaxX() - zoneRegion.getMinX()) + 1) * m_cellSize, - (abs(zoneRegion.getMaxY() - zoneRegion.getMinY()) + 1) * m_cellSize, - Qt::NoPen, QBrush(QColor(0, 0, 0, 50))); - - rectItem->setZValue(LAYER_BLACKOUT); - rectItem->setData(ZONE_NAME, QString(LAYER_BLACKOUT_NAME)); - return rectItem; -} - -void LandscapeScene::deleteItemZone(const ZonePosition &zonePos) -{ - QGraphicsItem *item = itemAt(zonePos.x * m_cellSize, abs(zonePos.y) * m_cellSize); - if ((item != 0) && (item->data(ZONE_NAME).toString() != QString(LAYER_BLACKOUT_NAME))) - { - removeItem(item); - delete item; - } -} - -void LandscapeScene::addZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) -{ - for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) - { - for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) - { - - std::string zoneName = zoneRegion.getName(i, j); - if (zoneName == STRING_UNUSED) - { - ZonePosition zonePos(i, j, -1); - QGraphicsItem *item = createItemEmptyZone(zonePos); - } - else if (!zoneName.empty()) - { - LigoData data; - ZonePosition zonePos(i, j, -1); - data.zoneName = zoneName; - data.rot = zoneRegion.getRot(i, j); - data.flip = zoneRegion.getFlip(i, j); - data.posX = zoneRegion.getPosX(i, j); - data.posY = zoneRegion.getPosY(i, j); - QGraphicsItem *item = createItemZone(data, zonePos); - } - } - } -} - -void LandscapeScene::delZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) -{ - for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) - { - for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) - { - deleteItemZone(ZonePosition(i, -j, -1)); - } - } -} - -void LandscapeScene::snapshot(const QString &fileName, int width, int height, const QRectF &landRect) -{ - if (m_zoneBuilder == 0) - return; - - // Create image - QImage image(landRect.width(), landRect.height(), QImage::Format_RGB888); - QPainter painter(&image); - painter.setRenderHint(QPainter::Antialiasing, true); - - // Add white background - painter.setBrush(QBrush(Qt::white)); - painter.setPen(Qt::NoPen); - painter.drawRect(0, 0, landRect.width(), landRect.height()); - - // Paint landscape - render(&painter, QRectF(0, 0, landRect.width(), landRect.height()), landRect); - - QImage scaledImage = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - scaledImage.save(fileName); -} - -QString LandscapeScene::zoneNameFromMousePos() const -{ - if ((m_posY > 0) || (m_posY < -MAX_SCENE_HEIGHT) || - (m_posX < 0) || (m_posX > MAX_SCENE_WIDTH)) - return "NOT A VALID ZONE"; - - return QString("%1_%2%3 %4 %5 ").arg(-m_posY).arg(QChar('A' + (m_posX/26))). - arg(QChar('A' + (m_posX%26))).arg(m_mouseX, 0,'f',2).arg(-m_mouseY, 0,'f',2); -} - -void LandscapeScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - qreal x = mouseEvent->scenePos().x(); - qreal y = mouseEvent->scenePos().y(); - if ((x < 0) || (y < 0)) - return; - - m_posX = sint32(floor(x / m_cellSize)); - m_posY = sint32(-floor(y / m_cellSize)); - - if (m_zoneBuilder == 0) - return; - if (m_transitionMode) - { - if (mouseEvent->button() == Qt::LeftButton) - - // Need add offset(= cellSize) on y axes - m_zoneBuilder->addTransition(sint(x), sint(-y + m_cellSize)); - } - else - { - if (mouseEvent->button() == Qt::LeftButton) - m_zoneBuilder->addZone(m_posX, m_posY); - else if (mouseEvent->button() == Qt::RightButton) - m_zoneBuilder->delZone(m_posX, m_posY); - } - m_mouseButton = mouseEvent->button(); - - QGraphicsScene::mousePressEvent(mouseEvent); -} - -void LandscapeScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - qreal x = mouseEvent->scenePos().x(); - qreal y = mouseEvent->scenePos().y(); - - sint32 posX = sint32(floor(x / m_cellSize)); - sint32 posY = sint32(-floor(y / m_cellSize)); - - if ((m_posX != posX || m_posY != posY) && - (m_mouseButton == Qt::LeftButton || - m_mouseButton == Qt::RightButton)) - { - if (m_transitionMode) - { - } - else - { - if (m_mouseButton == Qt::LeftButton) - m_zoneBuilder->addZone(posX, posY); - else if (m_mouseButton == Qt::RightButton) - m_zoneBuilder->delZone(posX, posY); - } - m_posX = posX; - m_posY = posY; - QApplication::processEvents(); - } - - m_posX = posX; - m_posY = posY; - - m_mouseX = mouseEvent->scenePos().x(); - m_mouseY = mouseEvent->scenePos().y() - m_cellSize; - QGraphicsScene::mouseMoveEvent(mouseEvent); -} - -void LandscapeScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - m_mouseButton = Qt::NoButton; -} - -bool LandscapeScene::checkUnderZone(const int posX, const int posY) -{ - QGraphicsItem *item = itemAt((posX * m_cellSize), abs(posY) * m_cellSize); - if (item != 0) - { - //if (item->data(ZONE_NAME) == QString(LAYER_BLACKOUT_NAME)) - // return false; - //else - return true; - } - return false; -} - -bool LandscapeScene::transitionMode() const -{ - return m_transitionMode; -} - -void LandscapeScene::setTransitionMode(bool enabled) -{ - m_transitionMode = enabled; - update(); -} - -void LandscapeScene::drawForeground(QPainter *painter, const QRectF &rect) -{ - QGraphicsScene::drawForeground(painter, rect); - if ((m_zoneBuilder->currentIdZoneRegion() != -1) && (m_transitionMode)) - drawTransition(painter, rect); -} - -void LandscapeScene::drawTransition(QPainter *painter, const QRectF &rect) -{ - int left = int(floor(rect.left() / m_cellSize)); - int right = int(floor(rect.right() / m_cellSize)); - int top = int(floor(rect.top() / m_cellSize)); - int bottom = int(floor(rect.bottom() / m_cellSize)); - - QVector redLines; - QVector whiteLines; - - for (int i = left; i < right + 1; ++i) - { - for (int j = top; j < bottom + 1; ++j) - { - // Get LIGO data - NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->currentZoneRegion()->ligoZoneRegion(); - uint8 ceUp = zoneRegion.getCutEdge (i, -j, 0); - uint8 ceLeft = zoneRegion.getCutEdge (i, -j, 2); - if ((ceUp > 0) && (ceUp < 3)) - { - // Calculate position vertical lines - int x1, x2, y1, y2; - - y1 = j * m_cellSize + m_cellSize / 12.0f; - y2 = y1 - (m_cellSize / 6.0f); - - x1 = i * m_cellSize + 3.0f * m_cellSize / 12.0f; - x2 = i * m_cellSize + 5.0f * m_cellSize / 12.0f; - if (ceUp == 1) - { - whiteLines.push_back(QLine(x1, y1, x1, y2)); - whiteLines.push_back(QLine(x2, y1, x2, y2)); - } - else - { - redLines.push_back(QLine(x1, y1, x1, y2)); - redLines.push_back(QLine(x2, y1, x2, y2)); - } - - x1 = i * m_cellSize + 7.0f * m_cellSize / 12.0f; - x2 = i * m_cellSize + 9.0f * m_cellSize / 12.0f; - if (ceUp == 1) - { - redLines.push_back(QLine(x1, y1, x1, y2)); - redLines.push_back(QLine(x2, y1, x2, y2)); - } - else - { - whiteLines.push_back(QLine(x1, y1, x1, y2)); - whiteLines.push_back(QLine(x2, y1, x2, y2)); - } - } - if ((ceLeft > 0) && (ceLeft < 3)) - { - // Calculate position horizontal lines - int x1, x2, y1, y2; - - x1 = i * m_cellSize - m_cellSize / 12.0f; - x2 = x1 + (m_cellSize / 6.0f); - - y1 = j * m_cellSize + 3.0f * m_cellSize / 12.0f; - y2 = j * m_cellSize + 5.0f * m_cellSize / 12.0f; - if (ceLeft == 1) - { - redLines.push_back(QLine(x1, y1, x2, y1)); - redLines.push_back(QLine(x1, y2, x2, y2)); - } - else - { - whiteLines.push_back(QLine(x1, y1, x2, y1)); - whiteLines.push_back(QLine(x1, y2, x2, y2)); - } - - y1 = j * m_cellSize + 7.0f * m_cellSize / 12.0f; - y2 = j * m_cellSize + 9.0f * m_cellSize / 12.0f; - if (ceLeft == 1) - { - whiteLines.push_back(QLine(x1, y1, x2, y1)); - whiteLines.push_back(QLine(x1, y2, x2, y2)); - } - else - { - redLines.push_back(QLine(x1, y1, x2, y1)); - redLines.push_back(QLine(x1, y2, x2, y2)); - } - } - } - } - - // Draw lines - painter->setPen(QPen(Qt::red, 0, Qt::SolidLine)); - painter->drawLines(redLines); - painter->setPen(QPen(Qt::white, 0, Qt::SolidLine)); - painter->drawLines(whiteLines); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_scene.h" +#include "pixmap_database.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include + +namespace LandscapeEditor +{ + +static const int ZONE_NAME = 0; +static const int LAYER_ZONES = 2; +static const int LAYER_EMPTY_ZONES = 3; +static const int LAYER_BLACKOUT = 4; +const char *const LAYER_BLACKOUT_NAME = "blackout"; + +const int MAX_SCENE_WIDTH = 256; +const int MAX_SCENE_HEIGHT = 256; + +LandscapeScene::LandscapeScene(int sizeCell, QObject *parent) + : QGraphicsScene(parent), + m_cellSize(sizeCell), + m_transitionMode(false), + m_mouseButton(Qt::NoButton), + m_zoneBuilder(0) +{ + setSceneRect(QRectF(0, m_cellSize, MAX_SCENE_WIDTH * m_cellSize, MAX_SCENE_HEIGHT * m_cellSize)); +} + +LandscapeScene::~LandscapeScene() +{ +} + +int LandscapeScene::cellSize() const +{ + return m_cellSize; +} + +void LandscapeScene::setZoneBuilder(ZoneBuilder *zoneBuilder) +{ + m_zoneBuilder = zoneBuilder; +} + +QGraphicsItem *LandscapeScene::createItemZone(const LigoData &data, const ZonePosition &zonePos) +{ + if ((data.zoneName == STRING_OUT_OF_BOUND) || (checkUnderZone(zonePos.x, zonePos.y))) + return 0; + + if (data.zoneName == STRING_UNUSED) + return createItemEmptyZone(zonePos); + + if ((m_zoneBuilder == 0) || (data.zoneName.empty())) + return 0; + + // Get image from pixmap database + QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(data.zoneName.c_str())); + if (pixmap == 0) + return 0; + + // Rotate the image counterclockwise + QMatrix matrix; + matrix.rotate(-data.rot * 90.0); + + QGraphicsPixmapItem *item; + + if (data.flip == 0) + { + item = addPixmap(pixmap->transformed(matrix, Qt::SmoothTransformation)); + } + else + { + // mirror image + QImage mirrorImage = pixmap->toImage(); + QPixmap mirrorPixmap = QPixmap::fromImage(mirrorImage.mirrored(true, false)); + item = addPixmap(mirrorPixmap.transformed(matrix, Qt::SmoothTransformation)); + } + // Enable bilinear filtering + item->setTransformationMode(Qt::SmoothTransformation); + + sint32 sizeX = 1, sizeY = 1; + sizeX = float(pixmap->width()) / m_zoneBuilder->pixmapDatabase()->textureSize(); + sizeY = float(pixmap->width()) / m_zoneBuilder->pixmapDatabase()->textureSize(); + + sint32 deltaX = 0, deltaY = 0; + + // Calculate offset for graphics item (for items with size that are larger than 1) + if ((sizeX > 1) || (sizeY > 1)) + { + if (data.flip == 0) + { + switch (data.rot) + { + case 0: + deltaX = -data.posX; + deltaY = -data.posY + sizeY - 1; + break; + case 1: + deltaX = -(sizeY - 1 - data.posY); + deltaY = -data.posX + sizeX - 1; + break; + case 2: + deltaX = -(sizeX - 1 - data.posX); + deltaY = data.posY; + break; + case 3: + deltaX = -data.posY; + deltaY = data.posX; + break; + } + } + else + { + switch (data.rot) + { + case 0: + deltaX = -(sizeX - 1 - data.posX); + deltaY = -data.posY + sizeY - 1; + break; + case 1: + deltaX = -(sizeY - 1 - data.posY); + deltaY = +data.posX; + break; + case 2: + deltaX = -data.posX; + deltaY = data.posY; + break; + case 3: + deltaX = -data.posY; + deltaY = -data.posX + sizeX - 1; + break; + } + } + } + + // Set position graphics item with offset for large piece + item->setPos((zonePos.x + deltaX) * m_cellSize, (abs(int(zonePos.y + deltaY))) * m_cellSize); + + // The size graphics item should be equal or proportional m_cellSize + item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); + + item->setData(ZONE_NAME, QString(data.zoneName.c_str())); + + // for not full item zone + item->setZValue(LAYER_ZONES); + + item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + return item; +} + +QGraphicsItem *LandscapeScene::createItemEmptyZone(const ZonePosition &zonePos) +{ + if (m_zoneBuilder == 0) + return 0; + + if (checkUnderZone(zonePos.x, zonePos.y)) + return 0; + + // Get image from pixmap database + QPixmap *pixmap = m_zoneBuilder->pixmapDatabase()->pixmap(QString(STRING_UNUSED)); + + if (pixmap == 0) + return 0; + + QGraphicsPixmapItem *item = addPixmap(*pixmap); + + // Enable bilinear filtering + item->setTransformationMode(Qt::SmoothTransformation); + + // Set position graphics item + item->setPos(zonePos.x * m_cellSize, abs(int(zonePos.y)) * m_cellSize); + + // The size graphics item should be equal or proportional m_cellSize + item->setScale(float(m_cellSize) / m_zoneBuilder->pixmapDatabase()->textureSize()); + + // for not full item zone + item->setZValue(LAYER_EMPTY_ZONES); + + item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + return item; +} + +QGraphicsRectItem *LandscapeScene::createLayerBlackout(const NLLIGO::CZoneRegion &zoneRegion) +{ + QGraphicsRectItem *rectItem = addRect(zoneRegion.getMinX() * m_cellSize, + abs(zoneRegion.getMaxY()) * m_cellSize, + (abs(zoneRegion.getMaxX() - zoneRegion.getMinX()) + 1) * m_cellSize, + (abs(zoneRegion.getMaxY() - zoneRegion.getMinY()) + 1) * m_cellSize, + Qt::NoPen, QBrush(QColor(0, 0, 0, 50))); + + rectItem->setZValue(LAYER_BLACKOUT); + rectItem->setData(ZONE_NAME, QString(LAYER_BLACKOUT_NAME)); + return rectItem; +} + +void LandscapeScene::deleteItemZone(const ZonePosition &zonePos) +{ + QGraphicsItem *item = itemAt(zonePos.x * m_cellSize, abs(zonePos.y) * m_cellSize); + if ((item != 0) && (item->data(ZONE_NAME).toString() != QString(LAYER_BLACKOUT_NAME))) + { + removeItem(item); + delete item; + } +} + +void LandscapeScene::addZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) + { + for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) + { + + std::string zoneName = zoneRegion.getName(i, j); + if (zoneName == STRING_UNUSED) + { + ZonePosition zonePos(i, j, -1); + QGraphicsItem *item = createItemEmptyZone(zonePos); + } + else if (!zoneName.empty()) + { + LigoData data; + ZonePosition zonePos(i, j, -1); + data.zoneName = zoneName; + data.rot = zoneRegion.getRot(i, j); + data.flip = zoneRegion.getFlip(i, j); + data.posX = zoneRegion.getPosX(i, j); + data.posY = zoneRegion.getPosY(i, j); + QGraphicsItem *item = createItemZone(data, zonePos); + } + } + } +} + +void LandscapeScene::delZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) + { + for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) + { + deleteItemZone(ZonePosition(i, -j, -1)); + } + } +} + +void LandscapeScene::snapshot(const QString &fileName, int width, int height, const QRectF &landRect) +{ + if (m_zoneBuilder == 0) + return; + + // Create image + QImage image(landRect.width(), landRect.height(), QImage::Format_RGB888); + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing, true); + + // Add white background + painter.setBrush(QBrush(Qt::white)); + painter.setPen(Qt::NoPen); + painter.drawRect(0, 0, landRect.width(), landRect.height()); + + // Paint landscape + render(&painter, QRectF(0, 0, landRect.width(), landRect.height()), landRect); + + QImage scaledImage = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + scaledImage.save(fileName); +} + +QString LandscapeScene::zoneNameFromMousePos() const +{ + if ((m_posY > 0) || (m_posY < -MAX_SCENE_HEIGHT) || + (m_posX < 0) || (m_posX > MAX_SCENE_WIDTH)) + return "NOT A VALID ZONE"; + + return QString("%1_%2%3 %4 %5 ").arg(-m_posY).arg(QChar('A' + (m_posX/26))). + arg(QChar('A' + (m_posX%26))).arg(m_mouseX, 0,'f',2).arg(-m_mouseY, 0,'f',2); +} + +void LandscapeScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + qreal x = mouseEvent->scenePos().x(); + qreal y = mouseEvent->scenePos().y(); + if ((x < 0) || (y < 0)) + return; + + m_posX = sint32(floor(x / m_cellSize)); + m_posY = sint32(-floor(y / m_cellSize)); + + if (m_zoneBuilder == 0) + return; + if (m_transitionMode) + { + if (mouseEvent->button() == Qt::LeftButton) + + // Need add offset(= cellSize) on y axes + m_zoneBuilder->addTransition(sint(x), sint(-y + m_cellSize)); + } + else + { + if (mouseEvent->button() == Qt::LeftButton) + m_zoneBuilder->addZone(m_posX, m_posY); + else if (mouseEvent->button() == Qt::RightButton) + m_zoneBuilder->delZone(m_posX, m_posY); + } + m_mouseButton = mouseEvent->button(); + + QGraphicsScene::mousePressEvent(mouseEvent); +} + +void LandscapeScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + qreal x = mouseEvent->scenePos().x(); + qreal y = mouseEvent->scenePos().y(); + + sint32 posX = sint32(floor(x / m_cellSize)); + sint32 posY = sint32(-floor(y / m_cellSize)); + + if ((m_posX != posX || m_posY != posY) && + (m_mouseButton == Qt::LeftButton || + m_mouseButton == Qt::RightButton)) + { + if (m_transitionMode) + { + } + else + { + if (m_mouseButton == Qt::LeftButton) + m_zoneBuilder->addZone(posX, posY); + else if (m_mouseButton == Qt::RightButton) + m_zoneBuilder->delZone(posX, posY); + } + m_posX = posX; + m_posY = posY; + QApplication::processEvents(); + } + + m_posX = posX; + m_posY = posY; + + m_mouseX = mouseEvent->scenePos().x(); + m_mouseY = mouseEvent->scenePos().y() - m_cellSize; + QGraphicsScene::mouseMoveEvent(mouseEvent); +} + +void LandscapeScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + m_mouseButton = Qt::NoButton; +} + +bool LandscapeScene::checkUnderZone(const int posX, const int posY) +{ + QGraphicsItem *item = itemAt((posX * m_cellSize), abs(posY) * m_cellSize); + if (item != 0) + { + //if (item->data(ZONE_NAME) == QString(LAYER_BLACKOUT_NAME)) + // return false; + //else + return true; + } + return false; +} + +bool LandscapeScene::transitionMode() const +{ + return m_transitionMode; +} + +void LandscapeScene::setTransitionMode(bool enabled) +{ + m_transitionMode = enabled; + update(); +} + +void LandscapeScene::drawForeground(QPainter *painter, const QRectF &rect) +{ + QGraphicsScene::drawForeground(painter, rect); + if ((m_zoneBuilder->currentIdZoneRegion() != -1) && (m_transitionMode)) + drawTransition(painter, rect); +} + +void LandscapeScene::drawTransition(QPainter *painter, const QRectF &rect) +{ + int left = int(floor(rect.left() / m_cellSize)); + int right = int(floor(rect.right() / m_cellSize)); + int top = int(floor(rect.top() / m_cellSize)); + int bottom = int(floor(rect.bottom() / m_cellSize)); + + QVector redLines; + QVector whiteLines; + + for (int i = left; i < right + 1; ++i) + { + for (int j = top; j < bottom + 1; ++j) + { + // Get LIGO data + NLLIGO::CZoneRegion &zoneRegion = m_zoneBuilder->currentZoneRegion()->ligoZoneRegion(); + uint8 ceUp = zoneRegion.getCutEdge (i, -j, 0); + uint8 ceLeft = zoneRegion.getCutEdge (i, -j, 2); + if ((ceUp > 0) && (ceUp < 3)) + { + // Calculate position vertical lines + int x1, x2, y1, y2; + + y1 = j * m_cellSize + m_cellSize / 12.0f; + y2 = y1 - (m_cellSize / 6.0f); + + x1 = i * m_cellSize + 3.0f * m_cellSize / 12.0f; + x2 = i * m_cellSize + 5.0f * m_cellSize / 12.0f; + if (ceUp == 1) + { + whiteLines.push_back(QLine(x1, y1, x1, y2)); + whiteLines.push_back(QLine(x2, y1, x2, y2)); + } + else + { + redLines.push_back(QLine(x1, y1, x1, y2)); + redLines.push_back(QLine(x2, y1, x2, y2)); + } + + x1 = i * m_cellSize + 7.0f * m_cellSize / 12.0f; + x2 = i * m_cellSize + 9.0f * m_cellSize / 12.0f; + if (ceUp == 1) + { + redLines.push_back(QLine(x1, y1, x1, y2)); + redLines.push_back(QLine(x2, y1, x2, y2)); + } + else + { + whiteLines.push_back(QLine(x1, y1, x1, y2)); + whiteLines.push_back(QLine(x2, y1, x2, y2)); + } + } + if ((ceLeft > 0) && (ceLeft < 3)) + { + // Calculate position horizontal lines + int x1, x2, y1, y2; + + x1 = i * m_cellSize - m_cellSize / 12.0f; + x2 = x1 + (m_cellSize / 6.0f); + + y1 = j * m_cellSize + 3.0f * m_cellSize / 12.0f; + y2 = j * m_cellSize + 5.0f * m_cellSize / 12.0f; + if (ceLeft == 1) + { + redLines.push_back(QLine(x1, y1, x2, y1)); + redLines.push_back(QLine(x1, y2, x2, y2)); + } + else + { + whiteLines.push_back(QLine(x1, y1, x2, y1)); + whiteLines.push_back(QLine(x1, y2, x2, y2)); + } + + y1 = j * m_cellSize + 7.0f * m_cellSize / 12.0f; + y2 = j * m_cellSize + 9.0f * m_cellSize / 12.0f; + if (ceLeft == 1) + { + whiteLines.push_back(QLine(x1, y1, x2, y1)); + whiteLines.push_back(QLine(x1, y2, x2, y2)); + } + else + { + redLines.push_back(QLine(x1, y1, x2, y1)); + redLines.push_back(QLine(x1, y2, x2, y2)); + } + } + } + } + + // Draw lines + painter->setPen(QPen(Qt::red, 0, Qt::SolidLine)); + painter->drawLines(redLines); + painter->setPen(QPen(Qt::white, 0, Qt::SolidLine)); + painter->drawLines(whiteLines); +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp index 2027831ae..0aaa1ef1f 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_scene_base.cpp @@ -1,331 +1,331 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_scene_base.h" -#include "pixmap_database.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include - -namespace LandscapeEditor -{ -static const int ZONE_NAME = 0; -static const int LAYER_ZONES = 2; -static const int LAYER_EMPTY_ZONES = 3; - -// TODO: delete -const char *const LAYER_BLACKOUT_NAME = "blackout"; - -const int MAX_SCENE_WIDTH = 256; -const int MAX_SCENE_HEIGHT = 256; - -LandscapeSceneBase::LandscapeSceneBase(int sizeCell, QObject *parent) - : QGraphicsScene(parent), - m_cellSize(sizeCell), - m_zoneBuilderBase(0) -{ - setSceneRect(QRectF(0, m_cellSize, MAX_SCENE_WIDTH * m_cellSize, MAX_SCENE_HEIGHT * m_cellSize)); -} - -LandscapeSceneBase::~LandscapeSceneBase() -{ -} - -int LandscapeSceneBase::cellSize() const -{ - return m_cellSize; -} - -void LandscapeSceneBase::setZoneBuilder(ZoneBuilderBase *zoneBuilder) -{ - m_zoneBuilderBase = zoneBuilder; -} - -QGraphicsItem *LandscapeSceneBase::createItemZone(const LigoData &data, const ZonePosition &zonePos) -{ - if ((data.zoneName == STRING_OUT_OF_BOUND) || (checkUnderZone(zonePos.x, zonePos.y))) - return 0; - - if (data.zoneName == STRING_UNUSED) - return createItemEmptyZone(zonePos); - - if ((m_zoneBuilderBase == 0) || (data.zoneName.empty())) - return 0; - - // Get image from pixmap database - QPixmap *pixmap = m_zoneBuilderBase->pixmapDatabase()->pixmap(QString(data.zoneName.c_str())); - if (pixmap == 0) - return 0; - - // Rotate the image counter clockwise - QMatrix matrix; - matrix.rotate(-data.rot * 90.0); - - QGraphicsPixmapItem *item; - - if (data.flip == 0) - { - item = addPixmap(pixmap->transformed(matrix, Qt::SmoothTransformation)); - } - else - { - // mirror image - QImage mirrorImage = pixmap->toImage(); - QPixmap mirrorPixmap = QPixmap::fromImage(mirrorImage.mirrored(true, false)); - item = addPixmap(mirrorPixmap.transformed(matrix, Qt::SmoothTransformation)); - } - // Enable bilinear filtering - item->setTransformationMode(Qt::SmoothTransformation); - - sint32 sizeX = 1, sizeY = 1; - sizeX = float(pixmap->width()) / m_zoneBuilderBase->pixmapDatabase()->textureSize(); - sizeY = float(pixmap->width()) / m_zoneBuilderBase->pixmapDatabase()->textureSize(); - - sint32 deltaX = 0, deltaY = 0; - - // Calculate offset for graphics item (for items with size that are larger than 1) - if ((sizeX > 1) || (sizeY > 1)) - { - if (data.flip == 0) - { - switch (data.rot) - { - case 0: - deltaX = -data.posX; - deltaY = -data.posY + sizeY - 1; - break; - case 1: - deltaX = -(sizeY - 1 - data.posY); - deltaY = -data.posX + sizeX - 1; - break; - case 2: - deltaX = -(sizeX - 1 - data.posX); - deltaY = data.posY; - break; - case 3: - deltaX = -data.posY; - deltaY = data.posX; - break; - } - } - else - { - switch (data.rot) - { - case 0: - deltaX = -(sizeX - 1 - data.posX); - deltaY = -data.posY + sizeY - 1; - break; - case 1: - deltaX = -(sizeY - 1 - data.posY); - deltaY = +data.posX; - break; - case 2: - deltaX = -data.posX; - deltaY = data.posY; - break; - case 3: - deltaX = -data.posY; - deltaY = -data.posX + sizeX - 1; - break; - } - } - } - - // Set position graphics item with offset for large piece - item->setPos((zonePos.x + deltaX) * m_cellSize, (abs(int(zonePos.y + deltaY))) * m_cellSize); - - // The size graphics item should be equal or proportional m_cellSize - item->setScale(float(m_cellSize) / m_zoneBuilderBase->pixmapDatabase()->textureSize()); - - item->setData(ZONE_NAME, QString(data.zoneName.c_str())); - - // for not full item zone - item->setZValue(LAYER_ZONES); - - item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); - - return item; -} - -QGraphicsItem *LandscapeSceneBase::createItemEmptyZone(const ZonePosition &zonePos) -{ - if (m_zoneBuilderBase == 0) - return 0; - - if (checkUnderZone(zonePos.x, zonePos.y)) - return 0; - - // Get image from pixmap database - QPixmap *pixmap = m_zoneBuilderBase->pixmapDatabase()->pixmap(QString(STRING_UNUSED)); - if (pixmap == 0) - return 0; - - QGraphicsPixmapItem *item = addPixmap(*pixmap); - - // Enable bilinear filtering - item->setTransformationMode(Qt::SmoothTransformation); - - // Set position graphics item - item->setPos(zonePos.x * m_cellSize, abs(int(zonePos.y)) * m_cellSize); - - // The size graphics item should be equal or proportional m_cellSize - item->setScale(float(m_cellSize) / m_zoneBuilderBase->pixmapDatabase()->textureSize()); - - // for not full item zone - item->setZValue(LAYER_EMPTY_ZONES); - - item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); - - return item; -} - -void LandscapeSceneBase::deleteItemZone(const ZonePosition &zonePos) -{ - QList listItems = items(QPointF(zonePos.x * m_cellSize + 10, abs(zonePos.y) * m_cellSize + 10), - Qt::IntersectsItemBoundingRect, Qt::AscendingOrder); - Q_FOREACH(QGraphicsItem *item, listItems) - { - if (qgraphicsitem_cast(item) != 0) - { - removeItem(item); - delete item; - return; - } - } -} - -void LandscapeSceneBase::addZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) -{ - for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) - { - for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) - { - - std::string zoneName = zoneRegion.getName(i, j); - if (zoneName == STRING_UNUSED) - { - ZonePosition zonePos(i, j, -1); - QGraphicsItem *item = createItemEmptyZone(zonePos); - } - else if (!zoneName.empty()) - { - LigoData data; - ZonePosition zonePos(i, j, -1); - data.zoneName = zoneName; - data.rot = zoneRegion.getRot(i, j); - data.flip = zoneRegion.getFlip(i, j); - data.posX = zoneRegion.getPosX(i, j); - data.posY = zoneRegion.getPosY(i, j); - QGraphicsItem *item = createItemZone(data, zonePos); - } - } - } -} - -void LandscapeSceneBase::delZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) -{ - for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) - { - for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) - { - - deleteItemZone(ZonePosition(i, -j, -1)); - } - } -} - -void LandscapeSceneBase::snapshot(const QString &fileName, int width, int height, const QRectF &landRect) -{ - if (m_zoneBuilderBase == 0) - return; - - // Create image - QImage image(landRect.width(), landRect.height(), QImage::Format_RGB888); - QPainter painter(&image); - painter.setRenderHint(QPainter::Antialiasing, true); - - // Add white background - painter.setBrush(QBrush(Qt::white)); - painter.setPen(Qt::NoPen); - painter.drawRect(0, 0, landRect.width(), landRect.height()); - - // Paint landscape - render(&painter, QRectF(0, 0, landRect.width(), landRect.height()), landRect); - - QImage scaledImage = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); - scaledImage.save(fileName); -} - -QString LandscapeSceneBase::zoneNameFromMousePos() const -{ - if ((m_posY > 0) || (m_posY < -MAX_SCENE_HEIGHT) || - (m_posX < 0) || (m_posX > MAX_SCENE_WIDTH)) - return "NOT A VALID ZONE"; - - return QString("%1_%2%3 %4 %5 ").arg(-m_posY+1).arg(QChar('A' + (m_posX/26))). - arg(QChar('A' + (m_posX%26))).arg(m_mouseX, 0,'f',2).arg(-m_mouseY, 0,'f',2); -} - -void LandscapeSceneBase::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - QGraphicsScene::mousePressEvent(mouseEvent); - - qreal x = mouseEvent->scenePos().x(); - qreal y = mouseEvent->scenePos().y(); - m_posX = sint32(floor(x / m_cellSize)); - m_posY = sint32(-floor(y / m_cellSize)); -} - -void LandscapeSceneBase::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - m_mouseX = mouseEvent->scenePos().x(); - m_mouseY = mouseEvent->scenePos().y() - m_cellSize; - - m_posX = sint32(floor(m_mouseX / m_cellSize)); - m_posY = sint32(-floor(m_mouseY / m_cellSize)); - - QGraphicsScene::mouseMoveEvent(mouseEvent); -} - -bool LandscapeSceneBase::checkUnderZone(const int posX, const int posY) -{ - // TODO: Why crash program? - // QList listItems = items(QPointF(posX * m_cellSize + 10, abs(posY) * m_cellSize + 10), - // Qt::IntersectsItemBoundingRect, Qt::AscendingOrder); - - QList listItems = items(); - - QPointF point(posX, abs(posY)); - Q_FOREACH(QGraphicsItem *item, listItems) - { - if (item->pos() == point) - { - if (qgraphicsitem_cast(item) != 0) - return true; - } - } - return false; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_scene_base.h" +#include "pixmap_database.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include + +namespace LandscapeEditor +{ +static const int ZONE_NAME = 0; +static const int LAYER_ZONES = 2; +static const int LAYER_EMPTY_ZONES = 3; + +// TODO: delete +const char *const LAYER_BLACKOUT_NAME = "blackout"; + +const int MAX_SCENE_WIDTH = 256; +const int MAX_SCENE_HEIGHT = 256; + +LandscapeSceneBase::LandscapeSceneBase(int sizeCell, QObject *parent) + : QGraphicsScene(parent), + m_cellSize(sizeCell), + m_zoneBuilderBase(0) +{ + setSceneRect(QRectF(0, m_cellSize, MAX_SCENE_WIDTH * m_cellSize, MAX_SCENE_HEIGHT * m_cellSize)); +} + +LandscapeSceneBase::~LandscapeSceneBase() +{ +} + +int LandscapeSceneBase::cellSize() const +{ + return m_cellSize; +} + +void LandscapeSceneBase::setZoneBuilder(ZoneBuilderBase *zoneBuilder) +{ + m_zoneBuilderBase = zoneBuilder; +} + +QGraphicsItem *LandscapeSceneBase::createItemZone(const LigoData &data, const ZonePosition &zonePos) +{ + if ((data.zoneName == STRING_OUT_OF_BOUND) || (checkUnderZone(zonePos.x, zonePos.y))) + return 0; + + if (data.zoneName == STRING_UNUSED) + return createItemEmptyZone(zonePos); + + if ((m_zoneBuilderBase == 0) || (data.zoneName.empty())) + return 0; + + // Get image from pixmap database + QPixmap *pixmap = m_zoneBuilderBase->pixmapDatabase()->pixmap(QString(data.zoneName.c_str())); + if (pixmap == 0) + return 0; + + // Rotate the image counter clockwise + QMatrix matrix; + matrix.rotate(-data.rot * 90.0); + + QGraphicsPixmapItem *item; + + if (data.flip == 0) + { + item = addPixmap(pixmap->transformed(matrix, Qt::SmoothTransformation)); + } + else + { + // mirror image + QImage mirrorImage = pixmap->toImage(); + QPixmap mirrorPixmap = QPixmap::fromImage(mirrorImage.mirrored(true, false)); + item = addPixmap(mirrorPixmap.transformed(matrix, Qt::SmoothTransformation)); + } + // Enable bilinear filtering + item->setTransformationMode(Qt::SmoothTransformation); + + sint32 sizeX = 1, sizeY = 1; + sizeX = float(pixmap->width()) / m_zoneBuilderBase->pixmapDatabase()->textureSize(); + sizeY = float(pixmap->width()) / m_zoneBuilderBase->pixmapDatabase()->textureSize(); + + sint32 deltaX = 0, deltaY = 0; + + // Calculate offset for graphics item (for items with size that are larger than 1) + if ((sizeX > 1) || (sizeY > 1)) + { + if (data.flip == 0) + { + switch (data.rot) + { + case 0: + deltaX = -data.posX; + deltaY = -data.posY + sizeY - 1; + break; + case 1: + deltaX = -(sizeY - 1 - data.posY); + deltaY = -data.posX + sizeX - 1; + break; + case 2: + deltaX = -(sizeX - 1 - data.posX); + deltaY = data.posY; + break; + case 3: + deltaX = -data.posY; + deltaY = data.posX; + break; + } + } + else + { + switch (data.rot) + { + case 0: + deltaX = -(sizeX - 1 - data.posX); + deltaY = -data.posY + sizeY - 1; + break; + case 1: + deltaX = -(sizeY - 1 - data.posY); + deltaY = +data.posX; + break; + case 2: + deltaX = -data.posX; + deltaY = data.posY; + break; + case 3: + deltaX = -data.posY; + deltaY = -data.posX + sizeX - 1; + break; + } + } + } + + // Set position graphics item with offset for large piece + item->setPos((zonePos.x + deltaX) * m_cellSize, (abs(int(zonePos.y + deltaY))) * m_cellSize); + + // The size graphics item should be equal or proportional m_cellSize + item->setScale(float(m_cellSize) / m_zoneBuilderBase->pixmapDatabase()->textureSize()); + + item->setData(ZONE_NAME, QString(data.zoneName.c_str())); + + // for not full item zone + item->setZValue(LAYER_ZONES); + + item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + return item; +} + +QGraphicsItem *LandscapeSceneBase::createItemEmptyZone(const ZonePosition &zonePos) +{ + if (m_zoneBuilderBase == 0) + return 0; + + if (checkUnderZone(zonePos.x, zonePos.y)) + return 0; + + // Get image from pixmap database + QPixmap *pixmap = m_zoneBuilderBase->pixmapDatabase()->pixmap(QString(STRING_UNUSED)); + if (pixmap == 0) + return 0; + + QGraphicsPixmapItem *item = addPixmap(*pixmap); + + // Enable bilinear filtering + item->setTransformationMode(Qt::SmoothTransformation); + + // Set position graphics item + item->setPos(zonePos.x * m_cellSize, abs(int(zonePos.y)) * m_cellSize); + + // The size graphics item should be equal or proportional m_cellSize + item->setScale(float(m_cellSize) / m_zoneBuilderBase->pixmapDatabase()->textureSize()); + + // for not full item zone + item->setZValue(LAYER_EMPTY_ZONES); + + item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + + return item; +} + +void LandscapeSceneBase::deleteItemZone(const ZonePosition &zonePos) +{ + QList listItems = items(QPointF(zonePos.x * m_cellSize + 10, abs(zonePos.y) * m_cellSize + 10), + Qt::IntersectsItemBoundingRect, Qt::AscendingOrder); + Q_FOREACH(QGraphicsItem *item, listItems) + { + if (qgraphicsitem_cast(item) != 0) + { + removeItem(item); + delete item; + return; + } + } +} + +void LandscapeSceneBase::addZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) + { + for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) + { + + std::string zoneName = zoneRegion.getName(i, j); + if (zoneName == STRING_UNUSED) + { + ZonePosition zonePos(i, j, -1); + QGraphicsItem *item = createItemEmptyZone(zonePos); + } + else if (!zoneName.empty()) + { + LigoData data; + ZonePosition zonePos(i, j, -1); + data.zoneName = zoneName; + data.rot = zoneRegion.getRot(i, j); + data.flip = zoneRegion.getFlip(i, j); + data.posX = zoneRegion.getPosX(i, j); + data.posY = zoneRegion.getPosY(i, j); + QGraphicsItem *item = createItemZone(data, zonePos); + } + } + } +} + +void LandscapeSceneBase::delZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + for (sint32 i = zoneRegion.getMinX(); i <= zoneRegion.getMaxX(); ++i) + { + for (sint32 j = zoneRegion.getMinY(); j <= zoneRegion.getMaxY(); ++j) + { + + deleteItemZone(ZonePosition(i, -j, -1)); + } + } +} + +void LandscapeSceneBase::snapshot(const QString &fileName, int width, int height, const QRectF &landRect) +{ + if (m_zoneBuilderBase == 0) + return; + + // Create image + QImage image(landRect.width(), landRect.height(), QImage::Format_RGB888); + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing, true); + + // Add white background + painter.setBrush(QBrush(Qt::white)); + painter.setPen(Qt::NoPen); + painter.drawRect(0, 0, landRect.width(), landRect.height()); + + // Paint landscape + render(&painter, QRectF(0, 0, landRect.width(), landRect.height()), landRect); + + QImage scaledImage = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + scaledImage.save(fileName); +} + +QString LandscapeSceneBase::zoneNameFromMousePos() const +{ + if ((m_posY > 0) || (m_posY < -MAX_SCENE_HEIGHT) || + (m_posX < 0) || (m_posX > MAX_SCENE_WIDTH)) + return "NOT A VALID ZONE"; + + return QString("%1_%2%3 %4 %5 ").arg(-m_posY+1).arg(QChar('A' + (m_posX/26))). + arg(QChar('A' + (m_posX%26))).arg(m_mouseX, 0,'f',2).arg(-m_mouseY, 0,'f',2); +} + +void LandscapeSceneBase::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + QGraphicsScene::mousePressEvent(mouseEvent); + + qreal x = mouseEvent->scenePos().x(); + qreal y = mouseEvent->scenePos().y(); + m_posX = sint32(floor(x / m_cellSize)); + m_posY = sint32(-floor(y / m_cellSize)); +} + +void LandscapeSceneBase::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + m_mouseX = mouseEvent->scenePos().x(); + m_mouseY = mouseEvent->scenePos().y() - m_cellSize; + + m_posX = sint32(floor(m_mouseX / m_cellSize)); + m_posY = sint32(-floor(m_mouseY / m_cellSize)); + + QGraphicsScene::mouseMoveEvent(mouseEvent); +} + +bool LandscapeSceneBase::checkUnderZone(const int posX, const int posY) +{ + // TODO: Why crash program? + // QList listItems = items(QPointF(posX * m_cellSize + 10, abs(posY) * m_cellSize + 10), + // Qt::IntersectsItemBoundingRect, Qt::AscendingOrder); + + QList listItems = items(); + + QPointF point(posX, abs(posY)); + Q_FOREACH(QGraphicsItem *item, listItems) + { + if (item->pos() == point) + { + if (qgraphicsitem_cast(item) != 0) + return true; + } + } + return false; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp index 7a612208a..74d6f9e7c 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/landscape_view.cpp @@ -1,254 +1,254 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "landscape_view.h" -#include "landscape_editor_constants.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include - -// Qt includes -#include - -namespace LandscapeEditor -{ - -LandscapeView::LandscapeView(QWidget *parent) - : QGraphicsView(parent), - m_visibleGrid(true), - m_visibleText(true) -{ - setTransformationAnchor(AnchorUnderMouse); - setBackgroundBrush(QBrush(Qt::lightGray)); - - m_cellSize = 160; - m_maxView = 0.06; - m_minView = 32.0; - m_maxViewText = 0.6; - - //A modified version of centerOn(), handles special cases - setCenter(QPointF(500.0, 500.0)); -} - -LandscapeView::~LandscapeView() -{ -} - -bool LandscapeView::isVisibleGrid() const -{ - return m_visibleGrid; -} - -void LandscapeView::setVisibleGrid(bool visible) -{ - m_visibleGrid = visible; - scene()->update(); -} - -void LandscapeView::setVisibleText(bool visible) -{ - m_visibleText = visible; - scene()->update(); -} - -void LandscapeView::wheelEvent(QWheelEvent *event) -{ - //How fast we zoom - float numSteps = (( event->delta() / 8 ) / 15) * 1.2; - - QMatrix mat = matrix(); - QPointF mousePosition = event->pos(); - - mat.translate((width() / 2) - mousePosition.x(), (height() / 2) - mousePosition.y()); - - if ( numSteps > 0 ) - mat.scale(numSteps, numSteps); - else - mat.scale(-1 / numSteps, -1 / numSteps); - - mat.translate(mousePosition.x() - (width() / 2), mousePosition.y() - (height() / 2)); - - //Adjust to the new center for correct zooming - setMatrix(mat); - event->accept(); -} - -void LandscapeView::mousePressEvent(QMouseEvent *event) -{ - QGraphicsView::mousePressEvent(event); - if (event->button() != Qt::MiddleButton) - return; - - //For panning the view - m_lastPanPoint = event->pos(); - setCursor(Qt::ClosedHandCursor); -} - -void LandscapeView::mouseMoveEvent(QMouseEvent *event) -{ - if(!m_lastPanPoint.isNull()) - { - //Get how much we panned - QPointF delta = mapToScene(m_lastPanPoint) - mapToScene(event->pos()); - m_lastPanPoint = event->pos(); - - //Update the center ie. do the pan - setCenter(getCenter() + delta); - } - - QGraphicsView::mouseMoveEvent(event); -} - -void LandscapeView::mouseReleaseEvent(QMouseEvent *event) -{ - m_lastPanPoint = QPoint(); - setCursor(Qt::ArrowCursor); - QGraphicsView::mouseReleaseEvent(event); -} - -void LandscapeView::resizeEvent(QResizeEvent *event) -{ - //Get the rectangle of the visible area in scene coords - QRectF visibleArea = mapToScene(rect()).boundingRect(); - setCenter(visibleArea.center()); - - //Call the subclass resize so the scrollbars are updated correctly - QGraphicsView::resizeEvent(event); -} - -void LandscapeView::setCenter(const QPointF ¢erPoint) -{ - //Get the rectangle of the visible area in scene coords - QRectF visibleArea = mapToScene(rect()).boundingRect(); - - //Get the scene area - QRectF sceneBounds = sceneRect(); - - double boundX = visibleArea.width() / 2.0; - double boundY = visibleArea.height() / 2.0; - double boundWidth = sceneBounds.width() - 2.0 * boundX; - double boundHeight = sceneBounds.height() - 2.0 * boundY; - - //The max boundary that the centerPoint can be to - QRectF bounds(boundX, boundY, boundWidth, boundHeight); - - if(bounds.contains(centerPoint)) - { - //We are within the bounds - m_currentCenterPoint = centerPoint; - } - else - { - //We need to clamp or use the center of the screen - if(visibleArea.contains(sceneBounds)) - { - //Use the center of scene ie. we can see the whole scene - m_currentCenterPoint = sceneBounds.center(); - } - else - { - m_currentCenterPoint = centerPoint; - - //We need to clamp the center. The centerPoint is too large - if (centerPoint.x() > bounds.x() + bounds.width()) - m_currentCenterPoint.setX(bounds.x() + bounds.width()); - else if(centerPoint.x() < bounds.x()) - m_currentCenterPoint.setX(bounds.x()); - - if(centerPoint.y() > bounds.y() + bounds.height()) - m_currentCenterPoint.setY(bounds.y() + bounds.height()); - else if(centerPoint.y() < bounds.y()) - m_currentCenterPoint.setY(bounds.y()); - } - } - - //Update the scrollbars - centerOn(m_currentCenterPoint); -} - -QPointF LandscapeView::getCenter() const -{ - //return m_currentCenterPoint; - return mapToScene(viewport()->rect().center()); -} - -void LandscapeView::drawForeground(QPainter *painter, const QRectF &rect) -{ - QGraphicsView::drawForeground(painter, rect); - - if (!m_visibleGrid) - return; - - painter->setPen(QPen(Qt::white, 0, Qt::SolidLine)); - drawGrid(painter, rect); - - if (!m_visibleText) - return; - - if (transform().m11() > m_maxViewText) - { - painter->setPen(QPen(Qt::white, 0.5, Qt::SolidLine)); - drawZoneNames(painter, rect); - } -} - -void LandscapeView::drawGrid(QPainter *painter, const QRectF &rect) -{ - qreal left = m_cellSize * floor(rect.left() / m_cellSize); - qreal top = m_cellSize * floor(rect.top() / m_cellSize); - - QVector lines; - - // Calculate vertical lines - while (left < rect.right()) - { - lines.push_back(QLine(int(left), int(rect.bottom()), int(left), int(rect.top()))); - left += m_cellSize; - } - - // Calculate horizontal lines - while (top < rect.bottom()) - { - lines.push_back(QLine(int(rect.left()), int(top), int(rect.right()), int(top))); - top += m_cellSize; - } - - // Draw lines - painter->drawLines(lines); -} - -void LandscapeView::drawZoneNames(QPainter *painter, const QRectF &rect) -{ - int leftSide = int(floor(rect.left() / m_cellSize)); - int rightSide = int(floor(rect.right() / m_cellSize)); - int topSide = int(floor(rect.top() / m_cellSize)); - int bottomSide = int(floor(rect.bottom() / m_cellSize)); - - for (int i = leftSide; i < rightSide + 1; ++i) - { - for (int j = topSide; j < bottomSide + 1; ++j) - { - QString text = QString("%1_%2%3").arg(j).arg(QChar('A' + (i / 26))).arg(QChar('A' + (i % 26))); - painter->drawText(i * m_cellSize + 5, j * m_cellSize + 15, text); - } - } -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "landscape_view.h" +#include "landscape_editor_constants.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include + +// Qt includes +#include + +namespace LandscapeEditor +{ + +LandscapeView::LandscapeView(QWidget *parent) + : QGraphicsView(parent), + m_visibleGrid(true), + m_visibleText(true) +{ + setTransformationAnchor(AnchorUnderMouse); + setBackgroundBrush(QBrush(Qt::lightGray)); + + m_cellSize = 160; + m_maxView = 0.06; + m_minView = 32.0; + m_maxViewText = 0.6; + + //A modified version of centerOn(), handles special cases + setCenter(QPointF(500.0, 500.0)); +} + +LandscapeView::~LandscapeView() +{ +} + +bool LandscapeView::isVisibleGrid() const +{ + return m_visibleGrid; +} + +void LandscapeView::setVisibleGrid(bool visible) +{ + m_visibleGrid = visible; + scene()->update(); +} + +void LandscapeView::setVisibleText(bool visible) +{ + m_visibleText = visible; + scene()->update(); +} + +void LandscapeView::wheelEvent(QWheelEvent *event) +{ + //How fast we zoom + float numSteps = (( event->delta() / 8 ) / 15) * 1.2; + + QMatrix mat = matrix(); + QPointF mousePosition = event->pos(); + + mat.translate((width() / 2) - mousePosition.x(), (height() / 2) - mousePosition.y()); + + if ( numSteps > 0 ) + mat.scale(numSteps, numSteps); + else + mat.scale(-1 / numSteps, -1 / numSteps); + + mat.translate(mousePosition.x() - (width() / 2), mousePosition.y() - (height() / 2)); + + //Adjust to the new center for correct zooming + setMatrix(mat); + event->accept(); +} + +void LandscapeView::mousePressEvent(QMouseEvent *event) +{ + QGraphicsView::mousePressEvent(event); + if (event->button() != Qt::MiddleButton) + return; + + //For panning the view + m_lastPanPoint = event->pos(); + setCursor(Qt::ClosedHandCursor); +} + +void LandscapeView::mouseMoveEvent(QMouseEvent *event) +{ + if(!m_lastPanPoint.isNull()) + { + //Get how much we panned + QPointF delta = mapToScene(m_lastPanPoint) - mapToScene(event->pos()); + m_lastPanPoint = event->pos(); + + //Update the center ie. do the pan + setCenter(getCenter() + delta); + } + + QGraphicsView::mouseMoveEvent(event); +} + +void LandscapeView::mouseReleaseEvent(QMouseEvent *event) +{ + m_lastPanPoint = QPoint(); + setCursor(Qt::ArrowCursor); + QGraphicsView::mouseReleaseEvent(event); +} + +void LandscapeView::resizeEvent(QResizeEvent *event) +{ + //Get the rectangle of the visible area in scene coords + QRectF visibleArea = mapToScene(rect()).boundingRect(); + setCenter(visibleArea.center()); + + //Call the subclass resize so the scrollbars are updated correctly + QGraphicsView::resizeEvent(event); +} + +void LandscapeView::setCenter(const QPointF ¢erPoint) +{ + //Get the rectangle of the visible area in scene coords + QRectF visibleArea = mapToScene(rect()).boundingRect(); + + //Get the scene area + QRectF sceneBounds = sceneRect(); + + double boundX = visibleArea.width() / 2.0; + double boundY = visibleArea.height() / 2.0; + double boundWidth = sceneBounds.width() - 2.0 * boundX; + double boundHeight = sceneBounds.height() - 2.0 * boundY; + + //The max boundary that the centerPoint can be to + QRectF bounds(boundX, boundY, boundWidth, boundHeight); + + if(bounds.contains(centerPoint)) + { + //We are within the bounds + m_currentCenterPoint = centerPoint; + } + else + { + //We need to clamp or use the center of the screen + if(visibleArea.contains(sceneBounds)) + { + //Use the center of scene ie. we can see the whole scene + m_currentCenterPoint = sceneBounds.center(); + } + else + { + m_currentCenterPoint = centerPoint; + + //We need to clamp the center. The centerPoint is too large + if (centerPoint.x() > bounds.x() + bounds.width()) + m_currentCenterPoint.setX(bounds.x() + bounds.width()); + else if(centerPoint.x() < bounds.x()) + m_currentCenterPoint.setX(bounds.x()); + + if(centerPoint.y() > bounds.y() + bounds.height()) + m_currentCenterPoint.setY(bounds.y() + bounds.height()); + else if(centerPoint.y() < bounds.y()) + m_currentCenterPoint.setY(bounds.y()); + } + } + + //Update the scrollbars + centerOn(m_currentCenterPoint); +} + +QPointF LandscapeView::getCenter() const +{ + //return m_currentCenterPoint; + return mapToScene(viewport()->rect().center()); +} + +void LandscapeView::drawForeground(QPainter *painter, const QRectF &rect) +{ + QGraphicsView::drawForeground(painter, rect); + + if (!m_visibleGrid) + return; + + painter->setPen(QPen(Qt::white, 0, Qt::SolidLine)); + drawGrid(painter, rect); + + if (!m_visibleText) + return; + + if (transform().m11() > m_maxViewText) + { + painter->setPen(QPen(Qt::white, 0.5, Qt::SolidLine)); + drawZoneNames(painter, rect); + } +} + +void LandscapeView::drawGrid(QPainter *painter, const QRectF &rect) +{ + qreal left = m_cellSize * floor(rect.left() / m_cellSize); + qreal top = m_cellSize * floor(rect.top() / m_cellSize); + + QVector lines; + + // Calculate vertical lines + while (left < rect.right()) + { + lines.push_back(QLine(int(left), int(rect.bottom()), int(left), int(rect.top()))); + left += m_cellSize; + } + + // Calculate horizontal lines + while (top < rect.bottom()) + { + lines.push_back(QLine(int(rect.left()), int(top), int(rect.right()), int(top))); + top += m_cellSize; + } + + // Draw lines + painter->drawLines(lines); +} + +void LandscapeView::drawZoneNames(QPainter *painter, const QRectF &rect) +{ + int leftSide = int(floor(rect.left() / m_cellSize)); + int rightSide = int(floor(rect.right() / m_cellSize)); + int topSide = int(floor(rect.top() / m_cellSize)); + int bottomSide = int(floor(rect.bottom() / m_cellSize)); + + for (int i = leftSide; i < rightSide + 1; ++i) + { + for (int j = topSide; j < bottomSide + 1; ++j) + { + QString text = QString("%1_%2%3").arg(j).arg(QChar('A' + (i / 26))).arg(QChar('A' + (i % 26))); + painter->drawText(i * m_cellSize + 5, j * m_cellSize + 15, text); + } + } +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp index 103a43052..d78c7c577 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_model.cpp @@ -1,137 +1,137 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "list_zones_model.h" -#include "builder_zone.h" - -// NeL includes -#include - -// STL includes -#include -#include - -// Qt includes -#include -#include - -namespace LandscapeEditor -{ - -ListZonesModel::ListZonesModel(int scaleRatio, QObject *parent) - : QAbstractListModel(parent), - m_scaleRatio(scaleRatio) -{ - -} -ListZonesModel::~ListZonesModel() -{ - resetModel(); -} - -int ListZonesModel::rowCount(const QModelIndex & /* parent */) const -{ - return m_listNames.count(); -} - -int ListZonesModel::columnCount(const QModelIndex & /* parent */) const -{ - return 1; -} - -QVariant ListZonesModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - switch (role) - { - case Qt::TextAlignmentRole: - return int(Qt::AlignLeft | Qt::AlignVCenter); - case Qt::DisplayRole: - return m_listNames.at(index.row()); - case Qt::DecorationRole: - { - QPixmap *pixmap = getPixmap(m_listNames.at(index.row())); - return qVariantFromValue(*pixmap); - } - default: - return QVariant(); - } -} - -QVariant ListZonesModel::headerData(int section, Qt::Orientation, int role) const -{ - return QVariant(); -} - -void ListZonesModel::setScaleRatio(int scaleRatio) -{ - m_scaleRatio = scaleRatio; -} - -void ListZonesModel::setListZones(QStringList &listZones) -{ - beginResetModel(); - m_listNames.clear(); - m_listNames = listZones; - endResetModel(); -} - -void ListZonesModel::resetModel() -{ - beginResetModel(); - QStringList listNames(m_pixmapMap.keys()); - Q_FOREACH(QString name, listNames) - { - QPixmap *pixmap = m_pixmapMap.value(name); - delete pixmap; - } - m_pixmapMap.clear(); - m_listNames.clear(); - endResetModel(); -} - -void ListZonesModel::rebuildModel(PixmapDatabase *pixmapDatabase) -{ - resetModel(); - - beginResetModel(); - QStringList listNames; - listNames = pixmapDatabase->listPixmaps(); - - Q_FOREACH(QString name, listNames) - { - QPixmap *pixmap = pixmapDatabase->pixmap(name); - QPixmap *smallPixmap = new QPixmap(pixmap->scaled(pixmap->width() / m_scaleRatio, pixmap->height() / m_scaleRatio)); - m_pixmapMap.insert(name, smallPixmap); - } - endResetModel(); -} - -QPixmap *ListZonesModel::getPixmap(const QString &zoneName) const -{ - QPixmap *result = 0; - if (!m_pixmapMap.contains(zoneName)) - nlwarning("QPixmap %s not found", zoneName.toStdString().c_str()); - else - result = m_pixmapMap.value(zoneName); - return result; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "list_zones_model.h" +#include "builder_zone.h" + +// NeL includes +#include + +// STL includes +#include +#include + +// Qt includes +#include +#include + +namespace LandscapeEditor +{ + +ListZonesModel::ListZonesModel(int scaleRatio, QObject *parent) + : QAbstractListModel(parent), + m_scaleRatio(scaleRatio) +{ + +} +ListZonesModel::~ListZonesModel() +{ + resetModel(); +} + +int ListZonesModel::rowCount(const QModelIndex & /* parent */) const +{ + return m_listNames.count(); +} + +int ListZonesModel::columnCount(const QModelIndex & /* parent */) const +{ + return 1; +} + +QVariant ListZonesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + switch (role) + { + case Qt::TextAlignmentRole: + return int(Qt::AlignLeft | Qt::AlignVCenter); + case Qt::DisplayRole: + return m_listNames.at(index.row()); + case Qt::DecorationRole: + { + QPixmap *pixmap = getPixmap(m_listNames.at(index.row())); + return qVariantFromValue(*pixmap); + } + default: + return QVariant(); + } +} + +QVariant ListZonesModel::headerData(int section, Qt::Orientation, int role) const +{ + return QVariant(); +} + +void ListZonesModel::setScaleRatio(int scaleRatio) +{ + m_scaleRatio = scaleRatio; +} + +void ListZonesModel::setListZones(QStringList &listZones) +{ + beginResetModel(); + m_listNames.clear(); + m_listNames = listZones; + endResetModel(); +} + +void ListZonesModel::resetModel() +{ + beginResetModel(); + QStringList listNames(m_pixmapMap.keys()); + Q_FOREACH(QString name, listNames) + { + QPixmap *pixmap = m_pixmapMap.value(name); + delete pixmap; + } + m_pixmapMap.clear(); + m_listNames.clear(); + endResetModel(); +} + +void ListZonesModel::rebuildModel(PixmapDatabase *pixmapDatabase) +{ + resetModel(); + + beginResetModel(); + QStringList listNames; + listNames = pixmapDatabase->listPixmaps(); + + Q_FOREACH(QString name, listNames) + { + QPixmap *pixmap = pixmapDatabase->pixmap(name); + QPixmap *smallPixmap = new QPixmap(pixmap->scaled(pixmap->width() / m_scaleRatio, pixmap->height() / m_scaleRatio)); + m_pixmapMap.insert(name, smallPixmap); + } + endResetModel(); +} + +QPixmap *ListZonesModel::getPixmap(const QString &zoneName) const +{ + QPixmap *result = 0; + if (!m_pixmapMap.contains(zoneName)) + nlwarning("QPixmap %s not found", zoneName.toStdString().c_str()); + else + result = m_pixmapMap.value(zoneName); + return result; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp index 554b19ca3..9d6ff8eb4 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/list_zones_widget.cpp @@ -1,308 +1,308 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "list_zones_widget.h" -#include "list_zones_model.h" -#include "builder_zone.h" - -// NeL includes -#include -#include -#include - -// STL includes -#include -#include - -// Qt includes -#include -#include - -namespace LandscapeEditor -{ - -ListZonesWidget::ListZonesWidget(QWidget *parent) - : QWidget(parent), - m_rotCycle(0), - m_flipCycle(0), - m_listZonesModel(0), - m_zoneBuilder(0) -{ - m_ui.setupUi(this); - - m_listZonesModel = new ListZonesModel(4, this); - m_ui.listView->setModel(m_listZonesModel); - - m_ui.addFilterButton_1->setChecked(false); - m_ui.addFilterButton_2->setChecked(false); - m_ui.addFilterButton_3->setChecked(false); - - connect(m_ui.categoryTypeComboBox_1, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_1(QString))); - connect(m_ui.categoryTypeComboBox_2, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_2(QString))); - connect(m_ui.categoryTypeComboBox_3, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_3(QString))); - connect(m_ui.categoryTypeComboBox_4, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_4(QString))); - connect(m_ui.categoryValueComboBox_1, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.categoryValueComboBox_2, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.categoryValueComboBox_3, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.categoryValueComboBox_4, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.logicComboBox_2, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.logicComboBox_3, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); - connect(m_ui.logicComboBox_4, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); -} - -ListZonesWidget::~ListZonesWidget() -{ -} - -void ListZonesWidget::updateUi() -{ - if (m_zoneBuilder == 0) - return; - - disableSignals(true); - std::vector listCategoryType; - m_zoneBuilder->getZoneBank().getCategoriesType(listCategoryType); - - QStringList listCategories; - - listCategories << STRING_UNUSED; - for (size_t i = 0; i < listCategoryType.size(); ++i) - listCategories << QString(listCategoryType[i].c_str()); - - m_ui.categoryTypeComboBox_1->clear(); - m_ui.categoryTypeComboBox_2->clear(); - m_ui.categoryTypeComboBox_3->clear(); - m_ui.categoryTypeComboBox_4->clear(); - m_ui.categoryValueComboBox_1->clear(); - m_ui.categoryValueComboBox_2->clear(); - m_ui.categoryValueComboBox_3->clear(); - m_ui.categoryValueComboBox_4->clear(); - - m_ui.categoryTypeComboBox_1->addItems(listCategories); - m_ui.categoryTypeComboBox_2->addItems(listCategories); - m_ui.categoryTypeComboBox_3->addItems(listCategories); - m_ui.categoryTypeComboBox_4->addItems(listCategories); - - disableSignals(false); - - m_listZonesModel->rebuildModel(m_zoneBuilder->pixmapDatabase()); -} - -QString ListZonesWidget::currentZoneName() -{ - QString zoneName = ""; - QModelIndex index = m_ui.listView->currentIndex(); - if (index.isValid()) - zoneName = index.data().toString(); - if (m_ui.zoneSelectComboBox->currentIndex() == 1) - { - // Random value - if (m_listSelection.size() > 0) - { - uint32 randZone = uint32(NLMISC::frand(m_listSelection.size())); - NLMISC::clamp(randZone, (uint32)0, uint32(m_listSelection.size() - 1)); - zoneName = m_listSelection[randZone]; - } - } - else if (m_ui.zoneSelectComboBox->currentIndex() == 2) - { - // Full cycle - if (m_listSelection.size() > 0) - { - zoneName = m_listSelection[m_zoneNameCycle]; - m_zoneNameCycle++; - m_zoneNameCycle = m_zoneNameCycle % m_listSelection.size(); - } - } - return zoneName; -} - -int ListZonesWidget::currentRot() -{ - int rot = m_ui.rotComboBox->currentIndex(); - if (rot == 4) - { - // Random value - uint32 randRot = uint32(NLMISC::frand(4.0)); - NLMISC::clamp(randRot, (uint32)0, (uint32)3); - rot = int(randRot); - } - else if (rot == 5) - { - // Full cycle - rot = m_rotCycle; - m_rotCycle++; - m_rotCycle = m_rotCycle % 4; - } - return rot; -} - -int ListZonesWidget::currentFlip() -{ - int flip = m_ui.flipComboBox->currentIndex(); - if (flip == 2) - { - // Random value - uint32 randFlip = uint32(NLMISC::frand(2.0)); - NLMISC::clamp (randFlip, (uint32)0, (uint32)1); - flip = int(randFlip); - } - else if (flip == 3) - { - // Full cycle - flip = m_flipCycle; - m_flipCycle++; - m_flipCycle = m_flipCycle % 2; - } - return flip; -} - -bool ListZonesWidget::isNotPropogate() const -{ - return m_ui.propogateCheckBox->isChecked(); -} - -bool ListZonesWidget::isForce() const -{ - return m_ui.forceCheckBox->isChecked(); -} - -void ListZonesWidget::setZoneBuilder(ZoneBuilder *zoneBuilder) -{ - m_zoneBuilder = zoneBuilder; -} - -void ListZonesWidget::updateFilters_1(const QString &value) -{ - disableSignals(true); - std::vector allCategoryValues; - m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); - m_ui.categoryValueComboBox_1->clear(); - for(size_t i = 0; i < allCategoryValues.size(); ++i) - m_ui.categoryValueComboBox_1->addItem(QString(allCategoryValues[i].c_str())); - - disableSignals(false); - updateListZones(); -} - -void ListZonesWidget::updateFilters_2(const QString &value) -{ - disableSignals(true); - std::vector allCategoryValues; - m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); - - m_ui.categoryValueComboBox_2->clear(); - for(size_t i = 0; i < allCategoryValues.size(); ++i) - m_ui.categoryValueComboBox_2->addItem(QString(allCategoryValues[i].c_str())); - - disableSignals(false); - updateListZones(); -} - -void ListZonesWidget::updateFilters_3(const QString &value) -{ - disableSignals(true); - std::vector allCategoryValues; - m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); - - m_ui.categoryValueComboBox_3->clear(); - for(size_t i = 0; i < allCategoryValues.size(); ++i) - m_ui.categoryValueComboBox_3->addItem(QString(allCategoryValues[i].c_str())); - - disableSignals(false); - updateListZones(); -} - -void ListZonesWidget::updateFilters_4(const QString &value) -{ - disableSignals(true); - std::vector allCategoryValues; - m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); - - m_ui.categoryValueComboBox_4->clear(); - for(size_t i = 0; i < allCategoryValues.size(); ++i) - m_ui.categoryValueComboBox_4->addItem(QString(allCategoryValues[i].c_str())); - - disableSignals(false); - updateListZones(); -} - -void ListZonesWidget::updateListZones() -{ - // Execute the filter - NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); - zoneBank.resetSelection (); - - if(m_ui.categoryTypeComboBox_1->currentIndex() > 0 ) - zoneBank.addOrSwitch (m_ui.categoryTypeComboBox_1->currentText().toStdString() - , m_ui.categoryValueComboBox_1->currentText().toStdString()); - - if(m_ui.categoryTypeComboBox_2->currentIndex() > 0 ) - { - if (m_ui.logicComboBox_2->currentIndex() == 0) // AND switch wanted - zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_2->currentText().toStdString() - ,m_ui.categoryValueComboBox_2->currentText().toStdString()); - else // OR switch wanted - zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_2->currentText().toStdString() - ,m_ui.categoryValueComboBox_2->currentText().toStdString()); - } - - if(m_ui.categoryTypeComboBox_3->currentIndex() > 0 ) - { - if (m_ui.logicComboBox_3->currentIndex() == 0) // AND switch wanted - zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_3->currentText().toStdString() - ,m_ui.categoryValueComboBox_3->currentText().toStdString()); - else // OR switch wanted - zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_3->currentText().toStdString() - ,m_ui.categoryValueComboBox_3->currentText().toStdString()); - } - - if(m_ui.categoryTypeComboBox_4->currentIndex() > 0 ) - { - if (m_ui.logicComboBox_4->currentIndex() == 0) // AND switch wanted - zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_4->currentText().toStdString() - ,m_ui.categoryValueComboBox_4->currentText().toStdString()); - else // OR switch wanted - zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_4->currentText().toStdString() - ,m_ui.categoryValueComboBox_4->currentText().toStdString()); - } - - std::vector currentSelection; - zoneBank.getSelection (currentSelection); - - m_listSelection.clear(); - m_zoneNameCycle = 0; - for (size_t i = 0; i < currentSelection.size(); ++i) - m_listSelection << currentSelection[i]->getName().c_str(); - - m_listZonesModel->setListZones(m_listSelection); -} - -void ListZonesWidget::disableSignals(bool block) -{ - m_ui.categoryTypeComboBox_1->blockSignals(block); - m_ui.categoryTypeComboBox_2->blockSignals(block); - m_ui.categoryTypeComboBox_3->blockSignals(block); - m_ui.categoryTypeComboBox_4->blockSignals(block); - m_ui.categoryValueComboBox_1->blockSignals(block); - m_ui.categoryValueComboBox_2->blockSignals(block); - m_ui.categoryValueComboBox_3->blockSignals(block); - m_ui.categoryValueComboBox_4->blockSignals(block); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "list_zones_widget.h" +#include "list_zones_model.h" +#include "builder_zone.h" + +// NeL includes +#include +#include +#include + +// STL includes +#include +#include + +// Qt includes +#include +#include + +namespace LandscapeEditor +{ + +ListZonesWidget::ListZonesWidget(QWidget *parent) + : QWidget(parent), + m_rotCycle(0), + m_flipCycle(0), + m_listZonesModel(0), + m_zoneBuilder(0) +{ + m_ui.setupUi(this); + + m_listZonesModel = new ListZonesModel(4, this); + m_ui.listView->setModel(m_listZonesModel); + + m_ui.addFilterButton_1->setChecked(false); + m_ui.addFilterButton_2->setChecked(false); + m_ui.addFilterButton_3->setChecked(false); + + connect(m_ui.categoryTypeComboBox_1, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_1(QString))); + connect(m_ui.categoryTypeComboBox_2, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_2(QString))); + connect(m_ui.categoryTypeComboBox_3, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_3(QString))); + connect(m_ui.categoryTypeComboBox_4, SIGNAL(currentIndexChanged(QString)), this, SLOT(updateFilters_4(QString))); + connect(m_ui.categoryValueComboBox_1, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.categoryValueComboBox_2, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.categoryValueComboBox_3, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.categoryValueComboBox_4, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.logicComboBox_2, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.logicComboBox_3, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); + connect(m_ui.logicComboBox_4, SIGNAL(currentIndexChanged(int)), this, SLOT(updateListZones())); +} + +ListZonesWidget::~ListZonesWidget() +{ +} + +void ListZonesWidget::updateUi() +{ + if (m_zoneBuilder == 0) + return; + + disableSignals(true); + std::vector listCategoryType; + m_zoneBuilder->getZoneBank().getCategoriesType(listCategoryType); + + QStringList listCategories; + + listCategories << STRING_UNUSED; + for (size_t i = 0; i < listCategoryType.size(); ++i) + listCategories << QString(listCategoryType[i].c_str()); + + m_ui.categoryTypeComboBox_1->clear(); + m_ui.categoryTypeComboBox_2->clear(); + m_ui.categoryTypeComboBox_3->clear(); + m_ui.categoryTypeComboBox_4->clear(); + m_ui.categoryValueComboBox_1->clear(); + m_ui.categoryValueComboBox_2->clear(); + m_ui.categoryValueComboBox_3->clear(); + m_ui.categoryValueComboBox_4->clear(); + + m_ui.categoryTypeComboBox_1->addItems(listCategories); + m_ui.categoryTypeComboBox_2->addItems(listCategories); + m_ui.categoryTypeComboBox_3->addItems(listCategories); + m_ui.categoryTypeComboBox_4->addItems(listCategories); + + disableSignals(false); + + m_listZonesModel->rebuildModel(m_zoneBuilder->pixmapDatabase()); +} + +QString ListZonesWidget::currentZoneName() +{ + QString zoneName = ""; + QModelIndex index = m_ui.listView->currentIndex(); + if (index.isValid()) + zoneName = index.data().toString(); + if (m_ui.zoneSelectComboBox->currentIndex() == 1) + { + // Random value + if (m_listSelection.size() > 0) + { + uint32 randZone = uint32(NLMISC::frand(m_listSelection.size())); + NLMISC::clamp(randZone, (uint32)0, uint32(m_listSelection.size() - 1)); + zoneName = m_listSelection[randZone]; + } + } + else if (m_ui.zoneSelectComboBox->currentIndex() == 2) + { + // Full cycle + if (m_listSelection.size() > 0) + { + zoneName = m_listSelection[m_zoneNameCycle]; + m_zoneNameCycle++; + m_zoneNameCycle = m_zoneNameCycle % m_listSelection.size(); + } + } + return zoneName; +} + +int ListZonesWidget::currentRot() +{ + int rot = m_ui.rotComboBox->currentIndex(); + if (rot == 4) + { + // Random value + uint32 randRot = uint32(NLMISC::frand(4.0)); + NLMISC::clamp(randRot, (uint32)0, (uint32)3); + rot = int(randRot); + } + else if (rot == 5) + { + // Full cycle + rot = m_rotCycle; + m_rotCycle++; + m_rotCycle = m_rotCycle % 4; + } + return rot; +} + +int ListZonesWidget::currentFlip() +{ + int flip = m_ui.flipComboBox->currentIndex(); + if (flip == 2) + { + // Random value + uint32 randFlip = uint32(NLMISC::frand(2.0)); + NLMISC::clamp (randFlip, (uint32)0, (uint32)1); + flip = int(randFlip); + } + else if (flip == 3) + { + // Full cycle + flip = m_flipCycle; + m_flipCycle++; + m_flipCycle = m_flipCycle % 2; + } + return flip; +} + +bool ListZonesWidget::isNotPropogate() const +{ + return m_ui.propogateCheckBox->isChecked(); +} + +bool ListZonesWidget::isForce() const +{ + return m_ui.forceCheckBox->isChecked(); +} + +void ListZonesWidget::setZoneBuilder(ZoneBuilder *zoneBuilder) +{ + m_zoneBuilder = zoneBuilder; +} + +void ListZonesWidget::updateFilters_1(const QString &value) +{ + disableSignals(true); + std::vector allCategoryValues; + m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); + m_ui.categoryValueComboBox_1->clear(); + for(size_t i = 0; i < allCategoryValues.size(); ++i) + m_ui.categoryValueComboBox_1->addItem(QString(allCategoryValues[i].c_str())); + + disableSignals(false); + updateListZones(); +} + +void ListZonesWidget::updateFilters_2(const QString &value) +{ + disableSignals(true); + std::vector allCategoryValues; + m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); + + m_ui.categoryValueComboBox_2->clear(); + for(size_t i = 0; i < allCategoryValues.size(); ++i) + m_ui.categoryValueComboBox_2->addItem(QString(allCategoryValues[i].c_str())); + + disableSignals(false); + updateListZones(); +} + +void ListZonesWidget::updateFilters_3(const QString &value) +{ + disableSignals(true); + std::vector allCategoryValues; + m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); + + m_ui.categoryValueComboBox_3->clear(); + for(size_t i = 0; i < allCategoryValues.size(); ++i) + m_ui.categoryValueComboBox_3->addItem(QString(allCategoryValues[i].c_str())); + + disableSignals(false); + updateListZones(); +} + +void ListZonesWidget::updateFilters_4(const QString &value) +{ + disableSignals(true); + std::vector allCategoryValues; + m_zoneBuilder->getZoneBank().getCategoryValues(value.toStdString(), allCategoryValues); + + m_ui.categoryValueComboBox_4->clear(); + for(size_t i = 0; i < allCategoryValues.size(); ++i) + m_ui.categoryValueComboBox_4->addItem(QString(allCategoryValues[i].c_str())); + + disableSignals(false); + updateListZones(); +} + +void ListZonesWidget::updateListZones() +{ + // Execute the filter + NLLIGO::CZoneBank &zoneBank = m_zoneBuilder->getZoneBank(); + zoneBank.resetSelection (); + + if(m_ui.categoryTypeComboBox_1->currentIndex() > 0 ) + zoneBank.addOrSwitch (m_ui.categoryTypeComboBox_1->currentText().toStdString() + , m_ui.categoryValueComboBox_1->currentText().toStdString()); + + if(m_ui.categoryTypeComboBox_2->currentIndex() > 0 ) + { + if (m_ui.logicComboBox_2->currentIndex() == 0) // AND switch wanted + zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_2->currentText().toStdString() + ,m_ui.categoryValueComboBox_2->currentText().toStdString()); + else // OR switch wanted + zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_2->currentText().toStdString() + ,m_ui.categoryValueComboBox_2->currentText().toStdString()); + } + + if(m_ui.categoryTypeComboBox_3->currentIndex() > 0 ) + { + if (m_ui.logicComboBox_3->currentIndex() == 0) // AND switch wanted + zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_3->currentText().toStdString() + ,m_ui.categoryValueComboBox_3->currentText().toStdString()); + else // OR switch wanted + zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_3->currentText().toStdString() + ,m_ui.categoryValueComboBox_3->currentText().toStdString()); + } + + if(m_ui.categoryTypeComboBox_4->currentIndex() > 0 ) + { + if (m_ui.logicComboBox_4->currentIndex() == 0) // AND switch wanted + zoneBank.addAndSwitch(m_ui.categoryTypeComboBox_4->currentText().toStdString() + ,m_ui.categoryValueComboBox_4->currentText().toStdString()); + else // OR switch wanted + zoneBank.addOrSwitch(m_ui.categoryTypeComboBox_4->currentText().toStdString() + ,m_ui.categoryValueComboBox_4->currentText().toStdString()); + } + + std::vector currentSelection; + zoneBank.getSelection (currentSelection); + + m_listSelection.clear(); + m_zoneNameCycle = 0; + for (size_t i = 0; i < currentSelection.size(); ++i) + m_listSelection << currentSelection[i]->getName().c_str(); + + m_listZonesModel->setListZones(m_listSelection); +} + +void ListZonesWidget::disableSignals(bool block) +{ + m_ui.categoryTypeComboBox_1->blockSignals(block); + m_ui.categoryTypeComboBox_2->blockSignals(block); + m_ui.categoryTypeComboBox_3->blockSignals(block); + m_ui.categoryTypeComboBox_4->blockSignals(block); + m_ui.categoryValueComboBox_1->blockSignals(block); + m_ui.categoryValueComboBox_2->blockSignals(block); + m_ui.categoryValueComboBox_3->blockSignals(block); + m_ui.categoryValueComboBox_4->blockSignals(block); +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml index ab71b7044..a0d32a22a 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/ovqt_plugin_landscape_editor.xml @@ -1,10 +1,10 @@ - - ovqt_plugin_landscape_editor - LandscapeEditor - 0.8 - GSoC2011_dnk-88 - Landscape editor ovqt plugin. - - - + + ovqt_plugin_landscape_editor + LandscapeEditor + 0.8 + GSoC2011_dnk-88 + Landscape editor ovqt plugin. + + + \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp index 15f8760be..91de95cce 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/pixmap_database.cpp @@ -1,154 +1,154 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "pixmap_database.h" - -// NeL includes -#include -#include - -// STL includes -#include -#include - -// Qt includes -#include -#include -#include -#include -#include - -namespace LandscapeEditor -{ - -PixmapDatabase::PixmapDatabase(int textureSize) - : m_textureSize(textureSize), - m_errorPixmap(0) -{ - // Create pixmap for case if pixmap and LIGO files not found - m_errorPixmap = new QPixmap(QSize(m_textureSize, m_textureSize)); - QPainter painter(m_errorPixmap); - painter.setRenderHint(QPainter::Antialiasing, true); - painter.fillRect(m_errorPixmap->rect(), QBrush(QColor(Qt::black))); - painter.setFont(QFont("Helvetica [Cronyx]", 14)); - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - painter.drawText(m_errorPixmap->rect(), Qt::AlignCenter | Qt::TextWordWrap, - QObject::tr("Pixmap and LIGO files not found.")); - painter.end(); -} - -PixmapDatabase::~PixmapDatabase() -{ - delete m_errorPixmap; - reset(); -} - -bool PixmapDatabase::loadPixmaps(const QString &zonePath, NLLIGO::CZoneBank &zoneBank, bool displayProgress) -{ - QProgressDialog *progressDialog; - std::vector listNames; - zoneBank.getCategoryValues ("zone", listNames); - if (displayProgress) - { - progressDialog = new QProgressDialog(QObject::tr("Loading ligo zones."), QObject::tr("Cancel"), 0, listNames.size()); - progressDialog->show(); - } - - for (uint i = 0; i < listNames.size(); ++i) - { - QApplication::processEvents(); - - if (displayProgress) - progressDialog->setValue(i); - - NLLIGO::CZoneBankElement *zoneBankItem = zoneBank.getElementByZoneName (listNames[i]); - - // Read the texture file - QString zonePixmapName(listNames[i].c_str()); - uint8 sizeX = zoneBankItem->getSizeX(); - uint8 sizeY = zoneBankItem->getSizeY(); - - QPixmap *pixmap = new QPixmap(zonePath + zonePixmapName + ".png"); - if (pixmap->isNull()) - { - // Generate filled pixmap if could not load pixmap - QPixmap *emptyPixmap = new QPixmap(QSize(sizeX * m_textureSize, sizeY * m_textureSize)); - QPainter painter(emptyPixmap); - painter.setRenderHint(QPainter::Antialiasing, true); - painter.fillRect(emptyPixmap->rect(), QBrush(QColor(Qt::black))); - painter.setFont(QFont("Helvetica [Cronyx]", 18)); - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - painter.drawText(emptyPixmap->rect(), Qt::AlignCenter, QObject::tr("Pixmap not found")); - painter.end(); - delete pixmap; - m_pixmapMap.insert(zonePixmapName, emptyPixmap); - nlwarning(QString("not found " + zonePath + zonePixmapName + ".png").toStdString().c_str()); - } - // All pixmaps must be have same size - else if (pixmap->width() != sizeX * m_textureSize) - { - QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(sizeX * m_textureSize, sizeY * m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - delete pixmap; - m_pixmapMap.insert(zonePixmapName, scaledPixmap); - } - else - m_pixmapMap.insert(zonePixmapName, pixmap); - } - - QPixmap *pixmap = new QPixmap(zonePath + "_unused_.png"); - QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(m_textureSize, m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - delete pixmap; - m_pixmapMap.insert(QString(STRING_UNUSED), scaledPixmap); - - if (displayProgress) - delete progressDialog; - - return true; -} - -void PixmapDatabase::reset() -{ - QStringList listNames(m_pixmapMap.keys()); - Q_FOREACH(QString name, listNames) - { - QPixmap *pixmap = m_pixmapMap.value(name); - delete pixmap; - } - m_pixmapMap.clear(); -} - -QStringList PixmapDatabase::listPixmaps() const -{ - return m_pixmapMap.keys(); -} - -QPixmap *PixmapDatabase::pixmap(const QString &zoneName) const -{ - QPixmap *result = m_errorPixmap; - if (!m_pixmapMap.contains(zoneName)) - nlwarning("QPixmap %s not found", zoneName.toStdString().c_str()); - else - result = m_pixmapMap.value(zoneName); - return result; -} - -int PixmapDatabase::textureSize() const -{ - return m_textureSize; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "pixmap_database.h" + +// NeL includes +#include +#include + +// STL includes +#include +#include + +// Qt includes +#include +#include +#include +#include +#include + +namespace LandscapeEditor +{ + +PixmapDatabase::PixmapDatabase(int textureSize) + : m_textureSize(textureSize), + m_errorPixmap(0) +{ + // Create pixmap for case if pixmap and LIGO files not found + m_errorPixmap = new QPixmap(QSize(m_textureSize, m_textureSize)); + QPainter painter(m_errorPixmap); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.fillRect(m_errorPixmap->rect(), QBrush(QColor(Qt::black))); + painter.setFont(QFont("Helvetica [Cronyx]", 14)); + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + painter.drawText(m_errorPixmap->rect(), Qt::AlignCenter | Qt::TextWordWrap, + QObject::tr("Pixmap and LIGO files not found.")); + painter.end(); +} + +PixmapDatabase::~PixmapDatabase() +{ + delete m_errorPixmap; + reset(); +} + +bool PixmapDatabase::loadPixmaps(const QString &zonePath, NLLIGO::CZoneBank &zoneBank, bool displayProgress) +{ + QProgressDialog *progressDialog; + std::vector listNames; + zoneBank.getCategoryValues ("zone", listNames); + if (displayProgress) + { + progressDialog = new QProgressDialog(QObject::tr("Loading ligo zones."), QObject::tr("Cancel"), 0, listNames.size()); + progressDialog->show(); + } + + for (uint i = 0; i < listNames.size(); ++i) + { + QApplication::processEvents(); + + if (displayProgress) + progressDialog->setValue(i); + + NLLIGO::CZoneBankElement *zoneBankItem = zoneBank.getElementByZoneName (listNames[i]); + + // Read the texture file + QString zonePixmapName(listNames[i].c_str()); + uint8 sizeX = zoneBankItem->getSizeX(); + uint8 sizeY = zoneBankItem->getSizeY(); + + QPixmap *pixmap = new QPixmap(zonePath + zonePixmapName + ".png"); + if (pixmap->isNull()) + { + // Generate filled pixmap if could not load pixmap + QPixmap *emptyPixmap = new QPixmap(QSize(sizeX * m_textureSize, sizeY * m_textureSize)); + QPainter painter(emptyPixmap); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.fillRect(emptyPixmap->rect(), QBrush(QColor(Qt::black))); + painter.setFont(QFont("Helvetica [Cronyx]", 18)); + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + painter.drawText(emptyPixmap->rect(), Qt::AlignCenter, QObject::tr("Pixmap not found")); + painter.end(); + delete pixmap; + m_pixmapMap.insert(zonePixmapName, emptyPixmap); + nlwarning(QString("not found " + zonePath + zonePixmapName + ".png").toStdString().c_str()); + } + // All pixmaps must be have same size + else if (pixmap->width() != sizeX * m_textureSize) + { + QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(sizeX * m_textureSize, sizeY * m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + delete pixmap; + m_pixmapMap.insert(zonePixmapName, scaledPixmap); + } + else + m_pixmapMap.insert(zonePixmapName, pixmap); + } + + QPixmap *pixmap = new QPixmap(zonePath + "_unused_.png"); + QPixmap *scaledPixmap = new QPixmap(pixmap->scaled(m_textureSize, m_textureSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); + delete pixmap; + m_pixmapMap.insert(QString(STRING_UNUSED), scaledPixmap); + + if (displayProgress) + delete progressDialog; + + return true; +} + +void PixmapDatabase::reset() +{ + QStringList listNames(m_pixmapMap.keys()); + Q_FOREACH(QString name, listNames) + { + QPixmap *pixmap = m_pixmapMap.value(name); + delete pixmap; + } + m_pixmapMap.clear(); +} + +QStringList PixmapDatabase::listPixmaps() const +{ + return m_pixmapMap.keys(); +} + +QPixmap *PixmapDatabase::pixmap(const QString &zoneName) const +{ + QPixmap *result = m_errorPixmap; + if (!m_pixmapMap.contains(zoneName)) + nlwarning("QPixmap %s not found", zoneName.toStdString().c_str()); + else + result = m_pixmapMap.value(zoneName); + return result; +} + +int PixmapDatabase::textureSize() const +{ + return m_textureSize; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp index f3eedb8a6..9cf5794b0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/project_settings_dialog.cpp @@ -1,60 +1,60 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "project_settings_dialog.h" -#include "landscape_editor_constants.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include - -namespace LandscapeEditor -{ - -ProjectSettingsDialog::ProjectSettingsDialog(const QString &dataPath, QWidget *parent) - : QDialog(parent) -{ - m_ui.setupUi(this); - m_ui.pathLineEdit->setText(dataPath); - setFixedHeight(sizeHint().height()); - connect(m_ui.selectPathButton, SIGNAL(clicked()), this, SLOT(selectPath())); -} - -ProjectSettingsDialog::~ProjectSettingsDialog() -{ -} - -QString ProjectSettingsDialog::dataPath() const -{ - return m_ui.pathLineEdit->text(); -} - -void ProjectSettingsDialog::selectPath() -{ - QString dataPath = QFileDialog::getExistingDirectory(this, tr("Select data path"), m_ui.pathLineEdit->text()); - if (!dataPath.isEmpty()) - m_ui.pathLineEdit->setText(dataPath); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "project_settings_dialog.h" +#include "landscape_editor_constants.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include + +namespace LandscapeEditor +{ + +ProjectSettingsDialog::ProjectSettingsDialog(const QString &dataPath, QWidget *parent) + : QDialog(parent) +{ + m_ui.setupUi(this); + m_ui.pathLineEdit->setText(dataPath); + setFixedHeight(sizeHint().height()); + connect(m_ui.selectPathButton, SIGNAL(clicked()), this, SLOT(selectPath())); +} + +ProjectSettingsDialog::~ProjectSettingsDialog() +{ +} + +QString ProjectSettingsDialog::dataPath() const +{ + return m_ui.pathLineEdit->text(); +} + +void ProjectSettingsDialog::selectPath() +{ + QString dataPath = QFileDialog::getExistingDirectory(this, tr("Select data path"), m_ui.pathLineEdit->text()); + if (!dataPath.isEmpty()) + m_ui.pathLineEdit->setText(dataPath); +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp index aeccd21b2..68a75b2e8 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/snapshot_dialog.cpp @@ -1,70 +1,70 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "snapshot_dialog.h" -#include "landscape_editor_constants.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace LandscapeEditor -{ - -SnapshotDialog::SnapshotDialog(QWidget *parent) - : QDialog(parent) -{ - m_ui.setupUi(this); - setFixedHeight(sizeHint().height()); -} - -SnapshotDialog::~SnapshotDialog() -{ -} - -bool SnapshotDialog::isCustomSize() const -{ - return m_ui.customSizeRadioButton->isChecked(); -} - -bool SnapshotDialog::isKeepRatio() const -{ - return m_ui.keepRatioCheckBox->isChecked(); -} - -int SnapshotDialog::resolutionZone() const -{ - return m_ui.resSpinBox->value(); -} - -int SnapshotDialog::widthSnapshot() const -{ - return m_ui.widthSpinBox->value(); -} - -int SnapshotDialog::heightSnapshot() const -{ - return m_ui.heightSpinBox->value(); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "snapshot_dialog.h" +#include "landscape_editor_constants.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include + +// Qt includes +#include +#include + +namespace LandscapeEditor +{ + +SnapshotDialog::SnapshotDialog(QWidget *parent) + : QDialog(parent) +{ + m_ui.setupUi(this); + setFixedHeight(sizeHint().height()); +} + +SnapshotDialog::~SnapshotDialog() +{ +} + +bool SnapshotDialog::isCustomSize() const +{ + return m_ui.customSizeRadioButton->isChecked(); +} + +bool SnapshotDialog::isKeepRatio() const +{ + return m_ui.keepRatioCheckBox->isChecked(); +} + +int SnapshotDialog::resolutionZone() const +{ + return m_ui.resSpinBox->value(); +} + +int SnapshotDialog::widthSnapshot() const +{ + return m_ui.widthSpinBox->value(); +} + +int SnapshotDialog::heightSnapshot() const +{ + return m_ui.heightSpinBox->value(); +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp index 874c5d533..5bf855297 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/landscape_editor/zone_region_editor.cpp @@ -1,181 +1,181 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "zone_region_editor.h" - -// NeL includes -#include -#include -#include -#include - -// Qt includes -#include - -namespace LandscapeEditor -{ - -ZoneRegionObject::ZoneRegionObject() -{ - m_fileName = ""; -} - -ZoneRegionObject::~ZoneRegionObject() -{ -} - -bool ZoneRegionObject::load(const std::string &fileName) -{ - bool result = true; - try - { - // Open it - NLMISC::CIFile fileIn; - if (fileIn.open(fileName)) - { - NLMISC::CIXml xml(true); - xml.init(fileIn); - m_zoneRegion.serial(xml); - } - else - { - nlwarning("Can't open file %s for reading", fileName.c_str()); - result = false; - } - } - catch (NLMISC::Exception &e) - { - nlwarning("Error reading file %s : %s", fileName.c_str(), e.what ()); - result = false; - } - if (result) - m_fileName = fileName; - return result; -} - -bool ZoneRegionObject::save() -{ - if (m_fileName.empty()) - return false; - - bool result = true; - // Save the landscape - try - { - - // Open file for writing - NLMISC::COFile fileOut; - if (fileOut.open(m_fileName, false, false, true)) - { - // Be careful with the flushing of the COXml object - { - NLMISC::COXml xmlOut; - xmlOut.init(&fileOut); - m_zoneRegion.serial(xmlOut); - // Done - m_modified = false; - } - fileOut.close(); - } - else - { - nlwarning("Can't open file %s for writing.", m_fileName.c_str()); - result = false; - } - } - catch (NLMISC::Exception &e) - { - nlwarning("Error writing file %s : %s", m_fileName.c_str(), e.what()); - result = false; - } - return result; -} - -std::string ZoneRegionObject::fileName() const -{ - return m_fileName; -} - -void ZoneRegionObject::setFileName(const std::string &fileName) -{ - m_fileName = fileName; -} - -void ZoneRegionObject::ligoData(LigoData &data, const sint32 x, const sint32 y) -{ - data.posX = m_zoneRegion.getPosX(x, y); - data.posY = m_zoneRegion.getPosY(x, y); - data.zoneName = m_zoneRegion.getName(x, y); - data.rot = m_zoneRegion.getRot(x, y); - data.flip = m_zoneRegion.getFlip(x, y); - data.sharingMatNames[0] = m_zoneRegion.getSharingMatNames(x, y, 0); - data.sharingMatNames[1] = m_zoneRegion.getSharingMatNames(x, y, 1); - data.sharingMatNames[2] = m_zoneRegion.getSharingMatNames(x, y, 2); - data.sharingMatNames[3] = m_zoneRegion.getSharingMatNames(x, y, 3); - data.sharingCutEdges[0] = m_zoneRegion.getSharingCutEdges(x, y, 0); - data.sharingCutEdges[1] = m_zoneRegion.getSharingCutEdges(x, y, 1); - data.sharingCutEdges[2] = m_zoneRegion.getSharingCutEdges(x, y, 2); - data.sharingCutEdges[3] = m_zoneRegion.getSharingCutEdges(x, y, 3); -} - -void ZoneRegionObject::setLigoData(const LigoData &data, const sint32 x, const sint32 y) -{ - m_zoneRegion.setPosX(x, y, data.posX); - m_zoneRegion.setPosY(x, y, data.posY); - m_zoneRegion.setName(x, y, data.zoneName); - m_zoneRegion.setRot(x, y, data.rot); - m_zoneRegion.setFlip(x, y, data.flip); - m_zoneRegion.setSharingMatNames(x, y, 0, data.sharingMatNames[0]); - m_zoneRegion.setSharingMatNames(x, y, 1, data.sharingMatNames[1]); - m_zoneRegion.setSharingMatNames(x, y, 2, data.sharingMatNames[2]); - m_zoneRegion.setSharingMatNames(x, y, 3, data.sharingMatNames[3]); - m_zoneRegion.setSharingCutEdges(x, y, 0, data.sharingCutEdges[0]); - m_zoneRegion.setSharingCutEdges(x, y, 1, data.sharingCutEdges[1]); - m_zoneRegion.setSharingCutEdges(x, y, 2, data.sharingCutEdges[2]); - m_zoneRegion.setSharingCutEdges(x, y, 3, data.sharingCutEdges[3]); -} - -NLLIGO::CZoneRegion &ZoneRegionObject::ligoZoneRegion() -{ - return m_zoneRegion; -} - -void ZoneRegionObject::setLigoZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) -{ - m_zoneRegion = zoneRegion; -} - -bool ZoneRegionObject::checkPos(const sint32 x, const sint32 y) -{ - return ((x >= m_zoneRegion.getMinX()) && - (x <= m_zoneRegion.getMaxX()) && - (y >= m_zoneRegion.getMinY()) && - (y <= m_zoneRegion.getMaxY())); -} - -bool ZoneRegionObject::isModified() const -{ - return m_modified; -} - -void ZoneRegionObject::setModified(bool modified) -{ - m_modified = modified; -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "zone_region_editor.h" + +// NeL includes +#include +#include +#include +#include + +// Qt includes +#include + +namespace LandscapeEditor +{ + +ZoneRegionObject::ZoneRegionObject() +{ + m_fileName = ""; +} + +ZoneRegionObject::~ZoneRegionObject() +{ +} + +bool ZoneRegionObject::load(const std::string &fileName) +{ + bool result = true; + try + { + // Open it + NLMISC::CIFile fileIn; + if (fileIn.open(fileName)) + { + NLMISC::CIXml xml(true); + xml.init(fileIn); + m_zoneRegion.serial(xml); + } + else + { + nlwarning("Can't open file %s for reading", fileName.c_str()); + result = false; + } + } + catch (NLMISC::Exception &e) + { + nlwarning("Error reading file %s : %s", fileName.c_str(), e.what ()); + result = false; + } + if (result) + m_fileName = fileName; + return result; +} + +bool ZoneRegionObject::save() +{ + if (m_fileName.empty()) + return false; + + bool result = true; + // Save the landscape + try + { + + // Open file for writing + NLMISC::COFile fileOut; + if (fileOut.open(m_fileName, false, false, true)) + { + // Be careful with the flushing of the COXml object + { + NLMISC::COXml xmlOut; + xmlOut.init(&fileOut); + m_zoneRegion.serial(xmlOut); + // Done + m_modified = false; + } + fileOut.close(); + } + else + { + nlwarning("Can't open file %s for writing.", m_fileName.c_str()); + result = false; + } + } + catch (NLMISC::Exception &e) + { + nlwarning("Error writing file %s : %s", m_fileName.c_str(), e.what()); + result = false; + } + return result; +} + +std::string ZoneRegionObject::fileName() const +{ + return m_fileName; +} + +void ZoneRegionObject::setFileName(const std::string &fileName) +{ + m_fileName = fileName; +} + +void ZoneRegionObject::ligoData(LigoData &data, const sint32 x, const sint32 y) +{ + data.posX = m_zoneRegion.getPosX(x, y); + data.posY = m_zoneRegion.getPosY(x, y); + data.zoneName = m_zoneRegion.getName(x, y); + data.rot = m_zoneRegion.getRot(x, y); + data.flip = m_zoneRegion.getFlip(x, y); + data.sharingMatNames[0] = m_zoneRegion.getSharingMatNames(x, y, 0); + data.sharingMatNames[1] = m_zoneRegion.getSharingMatNames(x, y, 1); + data.sharingMatNames[2] = m_zoneRegion.getSharingMatNames(x, y, 2); + data.sharingMatNames[3] = m_zoneRegion.getSharingMatNames(x, y, 3); + data.sharingCutEdges[0] = m_zoneRegion.getSharingCutEdges(x, y, 0); + data.sharingCutEdges[1] = m_zoneRegion.getSharingCutEdges(x, y, 1); + data.sharingCutEdges[2] = m_zoneRegion.getSharingCutEdges(x, y, 2); + data.sharingCutEdges[3] = m_zoneRegion.getSharingCutEdges(x, y, 3); +} + +void ZoneRegionObject::setLigoData(const LigoData &data, const sint32 x, const sint32 y) +{ + m_zoneRegion.setPosX(x, y, data.posX); + m_zoneRegion.setPosY(x, y, data.posY); + m_zoneRegion.setName(x, y, data.zoneName); + m_zoneRegion.setRot(x, y, data.rot); + m_zoneRegion.setFlip(x, y, data.flip); + m_zoneRegion.setSharingMatNames(x, y, 0, data.sharingMatNames[0]); + m_zoneRegion.setSharingMatNames(x, y, 1, data.sharingMatNames[1]); + m_zoneRegion.setSharingMatNames(x, y, 2, data.sharingMatNames[2]); + m_zoneRegion.setSharingMatNames(x, y, 3, data.sharingMatNames[3]); + m_zoneRegion.setSharingCutEdges(x, y, 0, data.sharingCutEdges[0]); + m_zoneRegion.setSharingCutEdges(x, y, 1, data.sharingCutEdges[1]); + m_zoneRegion.setSharingCutEdges(x, y, 2, data.sharingCutEdges[2]); + m_zoneRegion.setSharingCutEdges(x, y, 3, data.sharingCutEdges[3]); +} + +NLLIGO::CZoneRegion &ZoneRegionObject::ligoZoneRegion() +{ + return m_zoneRegion; +} + +void ZoneRegionObject::setLigoZoneRegion(const NLLIGO::CZoneRegion &zoneRegion) +{ + m_zoneRegion = zoneRegion; +} + +bool ZoneRegionObject::checkPos(const sint32 x, const sint32 y) +{ + return ((x >= m_zoneRegion.getMinX()) && + (x <= m_zoneRegion.getMaxX()) && + (y >= m_zoneRegion.getMinY()) && + (y <= m_zoneRegion.getMaxY())); +} + +bool ZoneRegionObject::isModified() const +{ + return m_modified; +} + +void ZoneRegionObject::setModified(bool modified) +{ + m_modified = modified; +} + +} /* namespace LandscapeEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt index 32f3950d9..144d0a652 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/CMakeLists.txt @@ -1,70 +1,70 @@ -INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${LIBXML2_INCLUDE_DIR} - ${QT_INCLUDES} - ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/qtpropertybrowser - ) - -FILE(GLOB SRC *.cpp *.h) - -SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h - ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) - -SET(OVQT_PLUGIN_WORLD_EDITOR_HDR world_editor_plugin.h - world_editor_window.h - world_editor_scene.h - world_editor_scene_item.h - primitives_model.h - primitives_view.h - project_settings_dialog.h - property_editor_widget.h - world_editor_settings_page.h -) - -SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui - project_settings_dialog.ui - property_editor_widget.ui - world_editor_settings_page.ui -) - -SET(OVQT_PLUGIN_WORLD_EDITOR_RCS world_editor.qrc) - -SET(QT_USE_QTGUI TRUE) -SET(QT_USE_QTOPENGL TRUE) - -QT4_ADD_RESOURCES(OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS ${OVQT_PLUGIN_WORLD_EDITOR_RCS}) -QT4_WRAP_CPP(OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC ${OVQT_PLUGIN_WORLD_EDITOR_HDR}) -QT4_WRAP_UI(OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS ${OVQT_PLUGIN_WORLD_EDITOR_UIS}) - -SOURCE_GROUP(QtResources FILES ${OVQT_PLUGIN_WORLD_EDITOR_UIS}) -SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS}) -SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS) -SOURCE_GROUP("World Editor Plugin" FILES ${SRC}) -SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) - -ADD_LIBRARY(ovqt_plugin_world_editor MODULE ${SRC} - ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} - ${OVQT_EXT_SYS_SRC} - ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS} - ${OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS}) - -TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor - ovqt_plugin_core - ovqt_plugin_landscape_editor - nelmisc - nel3d - qt_property_browser - ${QT_LIBRARIES} - ${QT_QTOPENGL_LIBRARY} -) - -NL_DEFAULT_PROPS(ovqt_plugin_world_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: World Editor") -NL_ADD_RUNTIME_FLAGS(ovqt_plugin_world_editor) -NL_ADD_LIB_SUFFIX(ovqt_plugin_world_editor) - -ADD_DEFINITIONS(-DWORLD_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) - -INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) - +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${QT_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR}/../../3rdparty/qtpropertybrowser + ) + +FILE(GLOB SRC *.cpp *.h) + +SET(OVQT_EXT_SYS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../extension_system/iplugin_spec.h) + +SET(OVQT_PLUGIN_WORLD_EDITOR_HDR world_editor_plugin.h + world_editor_window.h + world_editor_scene.h + world_editor_scene_item.h + primitives_model.h + primitives_view.h + project_settings_dialog.h + property_editor_widget.h + world_editor_settings_page.h +) + +SET(OVQT_PLUGIN_WORLD_EDITOR_UIS world_editor_window.ui + project_settings_dialog.ui + property_editor_widget.ui + world_editor_settings_page.ui +) + +SET(OVQT_PLUGIN_WORLD_EDITOR_RCS world_editor.qrc) + +SET(QT_USE_QTGUI TRUE) +SET(QT_USE_QTOPENGL TRUE) + +QT4_ADD_RESOURCES(OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS ${OVQT_PLUGIN_WORLD_EDITOR_RCS}) +QT4_WRAP_CPP(OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC ${OVQT_PLUGIN_WORLD_EDITOR_HDR}) +QT4_WRAP_UI(OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS ${OVQT_PLUGIN_WORLD_EDITOR_UIS}) + +SOURCE_GROUP(QtResources FILES ${OVQT_PLUGIN_WORLD_EDITOR_UIS}) +SOURCE_GROUP(QtGeneratedUiHdr FILES ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS}) +SOURCE_GROUP(QtGeneratedMocQrcSrc FILES ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS) +SOURCE_GROUP("World Editor Plugin" FILES ${SRC}) +SOURCE_GROUP("OVQT Extension System" FILES ${OVQT_EXT_SYS_SRC}) + +ADD_LIBRARY(ovqt_plugin_world_editor MODULE ${SRC} + ${OVQT_PLUGIN_WORLD_EDITOR_MOC_SRC} + ${OVQT_EXT_SYS_SRC} + ${OVQT_PLUGIN_WORLD_EDITOR_UI_HDRS} + ${OVQT_PLUGIN_WORLD_EDITOR_RC_SRCS}) + +TARGET_LINK_LIBRARIES( ovqt_plugin_world_editor + ovqt_plugin_core + ovqt_plugin_landscape_editor + nelmisc + nel3d + qt_property_browser + ${QT_LIBRARIES} + ${QT_QTOPENGL_LIBRARY} +) + +NL_DEFAULT_PROPS(ovqt_plugin_world_editor "NeL, Tools, 3D: Object Viewer Qt Plugin: World Editor") +NL_ADD_RUNTIME_FLAGS(ovqt_plugin_world_editor) +NL_ADD_LIB_SUFFIX(ovqt_plugin_world_editor) + +ADD_DEFINITIONS(-DWORLD_EDITOR_LIBRARY ${LIBXML2_DEFINITIONS} -DQT_PLUGIN -DQT_SHARED ${QT_DEFINITIONS}) + +INSTALL(TARGETS ovqt_plugin_world_editor LIBRARY DESTINATION ${OVQT_PLUGIN_DIR} RUNTIME DESTINATION ${NL_BIN_PREFIX} ARCHIVE DESTINATION ${OVQT_PLUGIN_DIR} COMPONENT tools3d) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/ovqt_plugin_world_editor.xml DESTINATION ${OVQT_PLUGIN_SPECS_DIR} COMPONENT tools3d) + diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml index 7a37eaf56..13a157a7e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/ovqt_plugin_world_editor.xml @@ -1,11 +1,11 @@ - - ovqt_plugin_world_editor - WorldEditor - 0.6 - GSoC2011_dnk-88 - Landscape editor ovqt plugin. - - - - + + ovqt_plugin_world_editor + WorldEditor + 0.6 + GSoC2011_dnk-88 + Landscape editor ovqt plugin. + + + + \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp index 12d3b994a..e14736bb0 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.cpp @@ -1,312 +1,312 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "primitive_item.h" -#include "world_editor_misc.h" -#include "world_editor_constants.h" - -#include "../landscape_editor/landscape_editor_constants.h" - -// NeL includes -#include - -// Qt includes -#include -#include - -namespace WorldEditor -{ - -Node::Node() - : m_parent(0) -{ - setData(Constants::PRIMITIVE_IS_VISIBLE, true); -} - -Node::~Node() -{ - if (m_parent) - m_parent->removeChildNode(this); - - qDeleteAll(m_children); - nlassert(m_children.isEmpty()); - m_data.clear(); -} - -void Node::prependChildNode(Node *node) -{ - // Node is already a child - nlassert(!m_children.contains(node)); - - // Node already has a parent - nlassert(!m_children.contains(node)); - - m_children.prepend(node); - node->m_parent = this; -} - -void Node::appendChildNode(Node *node) -{ - // Node is already a child - nlassert(!m_children.contains(node)); - - // Node already has a parent - nlassert(!m_children.contains(node)); - - m_children.append(node); - node->m_parent = this; -} - -void Node::insertChildNodeBefore(Node *node, Node *before) -{ - // Node is already a child - nlassert(!m_children.contains(node)); - - // Node already has a parent - nlassert(!m_children.contains(node)); - - int idx = before ? m_children.indexOf(before) : -1; - if (idx == -1) - m_children.append(node); - else - m_children.insert(idx, node); - node->m_parent = this; -} - -void Node::insertChildNodeAfter(Node *node, Node *after) -{ - // Node is already a child - nlassert(!m_children.contains(node)); - - // Node already has a parent - nlassert(!m_children.contains(node)); - - int idx = after ? m_children.indexOf(after) : -1; - if (idx == -1) - m_children.append(node); - else - m_children.insert(idx + 1, node); - node->m_parent = this; -} - -void Node::insertChildNode(int pos, Node *node) -{ - // Node is already a child - nlassert(!m_children.contains(node)); - - // Node already has a parent - nlassert(!m_children.contains(node)); - - m_children.insert(pos, node); - node->m_parent = this; -} - -void Node::removeChildNode(Node *node) -{ - nlassert(m_children.contains(node)); - nlassert(node->parent() == this); - - m_children.removeOne(node); - - node->m_parent = 0; -} - -Node *Node::child(int row) -{ - return m_children.at(row); -} - -int Node::childCount() const -{ - return m_children.count(); -} - -QVariant Node::data(int key) const -{ - return m_data[key]; -} - -void Node::setData(int key, const QVariant &data) -{ - m_data[key] = data; -} - -Node *Node::parent() -{ - return m_parent; -} - -int Node::row() const -{ - if (m_parent) - return m_parent->m_children.indexOf(const_cast(this)); - - return 0; -} - -Node::NodeType Node::type() const -{ - return BasicNodeType; -} - -WorldEditNode::WorldEditNode(const QString &name) -{ - setData(Qt::DisplayRole, name); - setData(Qt::DecorationRole, QIcon(Constants::ICON_WORLD_EDITOR)); -} - -WorldEditNode::~WorldEditNode() -{ -} - -void WorldEditNode::setContext(const QString &name) -{ - m_context = name; -} - -QString WorldEditNode::context() const -{ - return m_context; -} - -void WorldEditNode::setDataPath(const QString &path) -{ - m_dataPath = path; -} - -QString WorldEditNode::dataPath() const -{ - return m_dataPath; -} - -Node::NodeType WorldEditNode::type() const -{ - return WorldEditNodeType; -} - -LandscapeNode::LandscapeNode(const QString &name, int id) - : m_id(id), - m_fileName(name) -{ - setData(Qt::DisplayRole, name); - setData(Qt::DecorationRole, QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM)); -} - -LandscapeNode::~LandscapeNode() -{ -} - -QString LandscapeNode::fileName() const -{ - return m_fileName; -} - -int LandscapeNode::id() const -{ - return m_id; -} - -Node::NodeType LandscapeNode::type() const -{ - return LandscapeNodeType; -} - -PrimitiveNode::PrimitiveNode(NLLIGO::IPrimitive *primitive) - : m_primitive(primitive) -{ - setData(Qt::DisplayRole, QString(m_primitive->getName().c_str())); - setData(Qt::ToolTipRole, QString(m_primitive->getClassName().c_str())); - - std::string className; - m_primitive->getPropertyByName("class", className); - - // Set Icon - QString nameIcon = QString("%1/%2.ico").arg(Constants::PATH_TO_OLD_ICONS).arg(className.c_str()); - QIcon icon(nameIcon); - if (!QFile::exists(nameIcon)) - { - if (primitive->getParent() == NULL) - icon = QIcon(Constants::ICON_ROOT_PRIMITIVE); - else if (primitive->getNumChildren() == 0) - icon = QIcon(Constants::ICON_PROPERTY); - else - icon = QIcon(Constants::ICON_FOLDER); - } - setData(Qt::DecorationRole, icon); -} - -PrimitiveNode::~PrimitiveNode() -{ -} - -NLLIGO::IPrimitive *PrimitiveNode::primitive() const -{ - return m_primitive; -} - -const NLLIGO::CPrimitiveClass *PrimitiveNode::primitiveClass() const -{ - return Utils::ligoConfig()->getPrimitiveClass(*m_primitive); -} - -RootPrimitiveNode *PrimitiveNode::rootPrimitiveNode() -{ - Node *node = this; - while (node && (node->type() != Node::RootPrimitiveNodeType)) - node = node->parent(); - return static_cast(node); -} - -Node::NodeType PrimitiveNode::type() const -{ - return PrimitiveNodeType; -} - -RootPrimitiveNode::RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives) - : PrimitiveNode(primitives->RootNode), - m_fileName(name), - m_primitives(primitives) -{ - setData(Qt::DisplayRole, name); -} - -RootPrimitiveNode::~RootPrimitiveNode() -{ -} - -NLLIGO::CPrimitives *RootPrimitiveNode::primitives() const -{ - return m_primitives; -} - -void RootPrimitiveNode::setFileName(const QString &fileName) -{ - setData(Qt::DisplayRole, fileName); - m_fileName = fileName; -} - -QString RootPrimitiveNode::fileName() const -{ - return m_fileName; -} - -Node::NodeType RootPrimitiveNode::type() const -{ - return RootPrimitiveNodeType; -} - -} /* namespace WorldEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "primitive_item.h" +#include "world_editor_misc.h" +#include "world_editor_constants.h" + +#include "../landscape_editor/landscape_editor_constants.h" + +// NeL includes +#include + +// Qt includes +#include +#include + +namespace WorldEditor +{ + +Node::Node() + : m_parent(0) +{ + setData(Constants::PRIMITIVE_IS_VISIBLE, true); +} + +Node::~Node() +{ + if (m_parent) + m_parent->removeChildNode(this); + + qDeleteAll(m_children); + nlassert(m_children.isEmpty()); + m_data.clear(); +} + +void Node::prependChildNode(Node *node) +{ + // Node is already a child + nlassert(!m_children.contains(node)); + + // Node already has a parent + nlassert(!m_children.contains(node)); + + m_children.prepend(node); + node->m_parent = this; +} + +void Node::appendChildNode(Node *node) +{ + // Node is already a child + nlassert(!m_children.contains(node)); + + // Node already has a parent + nlassert(!m_children.contains(node)); + + m_children.append(node); + node->m_parent = this; +} + +void Node::insertChildNodeBefore(Node *node, Node *before) +{ + // Node is already a child + nlassert(!m_children.contains(node)); + + // Node already has a parent + nlassert(!m_children.contains(node)); + + int idx = before ? m_children.indexOf(before) : -1; + if (idx == -1) + m_children.append(node); + else + m_children.insert(idx, node); + node->m_parent = this; +} + +void Node::insertChildNodeAfter(Node *node, Node *after) +{ + // Node is already a child + nlassert(!m_children.contains(node)); + + // Node already has a parent + nlassert(!m_children.contains(node)); + + int idx = after ? m_children.indexOf(after) : -1; + if (idx == -1) + m_children.append(node); + else + m_children.insert(idx + 1, node); + node->m_parent = this; +} + +void Node::insertChildNode(int pos, Node *node) +{ + // Node is already a child + nlassert(!m_children.contains(node)); + + // Node already has a parent + nlassert(!m_children.contains(node)); + + m_children.insert(pos, node); + node->m_parent = this; +} + +void Node::removeChildNode(Node *node) +{ + nlassert(m_children.contains(node)); + nlassert(node->parent() == this); + + m_children.removeOne(node); + + node->m_parent = 0; +} + +Node *Node::child(int row) +{ + return m_children.at(row); +} + +int Node::childCount() const +{ + return m_children.count(); +} + +QVariant Node::data(int key) const +{ + return m_data[key]; +} + +void Node::setData(int key, const QVariant &data) +{ + m_data[key] = data; +} + +Node *Node::parent() +{ + return m_parent; +} + +int Node::row() const +{ + if (m_parent) + return m_parent->m_children.indexOf(const_cast(this)); + + return 0; +} + +Node::NodeType Node::type() const +{ + return BasicNodeType; +} + +WorldEditNode::WorldEditNode(const QString &name) +{ + setData(Qt::DisplayRole, name); + setData(Qt::DecorationRole, QIcon(Constants::ICON_WORLD_EDITOR)); +} + +WorldEditNode::~WorldEditNode() +{ +} + +void WorldEditNode::setContext(const QString &name) +{ + m_context = name; +} + +QString WorldEditNode::context() const +{ + return m_context; +} + +void WorldEditNode::setDataPath(const QString &path) +{ + m_dataPath = path; +} + +QString WorldEditNode::dataPath() const +{ + return m_dataPath; +} + +Node::NodeType WorldEditNode::type() const +{ + return WorldEditNodeType; +} + +LandscapeNode::LandscapeNode(const QString &name, int id) + : m_id(id), + m_fileName(name) +{ + setData(Qt::DisplayRole, name); + setData(Qt::DecorationRole, QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM)); +} + +LandscapeNode::~LandscapeNode() +{ +} + +QString LandscapeNode::fileName() const +{ + return m_fileName; +} + +int LandscapeNode::id() const +{ + return m_id; +} + +Node::NodeType LandscapeNode::type() const +{ + return LandscapeNodeType; +} + +PrimitiveNode::PrimitiveNode(NLLIGO::IPrimitive *primitive) + : m_primitive(primitive) +{ + setData(Qt::DisplayRole, QString(m_primitive->getName().c_str())); + setData(Qt::ToolTipRole, QString(m_primitive->getClassName().c_str())); + + std::string className; + m_primitive->getPropertyByName("class", className); + + // Set Icon + QString nameIcon = QString("%1/%2.ico").arg(Constants::PATH_TO_OLD_ICONS).arg(className.c_str()); + QIcon icon(nameIcon); + if (!QFile::exists(nameIcon)) + { + if (primitive->getParent() == NULL) + icon = QIcon(Constants::ICON_ROOT_PRIMITIVE); + else if (primitive->getNumChildren() == 0) + icon = QIcon(Constants::ICON_PROPERTY); + else + icon = QIcon(Constants::ICON_FOLDER); + } + setData(Qt::DecorationRole, icon); +} + +PrimitiveNode::~PrimitiveNode() +{ +} + +NLLIGO::IPrimitive *PrimitiveNode::primitive() const +{ + return m_primitive; +} + +const NLLIGO::CPrimitiveClass *PrimitiveNode::primitiveClass() const +{ + return Utils::ligoConfig()->getPrimitiveClass(*m_primitive); +} + +RootPrimitiveNode *PrimitiveNode::rootPrimitiveNode() +{ + Node *node = this; + while (node && (node->type() != Node::RootPrimitiveNodeType)) + node = node->parent(); + return static_cast(node); +} + +Node::NodeType PrimitiveNode::type() const +{ + return PrimitiveNodeType; +} + +RootPrimitiveNode::RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives) + : PrimitiveNode(primitives->RootNode), + m_fileName(name), + m_primitives(primitives) +{ + setData(Qt::DisplayRole, name); +} + +RootPrimitiveNode::~RootPrimitiveNode() +{ +} + +NLLIGO::CPrimitives *RootPrimitiveNode::primitives() const +{ + return m_primitives; +} + +void RootPrimitiveNode::setFileName(const QString &fileName) +{ + setData(Qt::DisplayRole, fileName); + m_fileName = fileName; +} + +QString RootPrimitiveNode::fileName() const +{ + return m_fileName; +} + +Node::NodeType RootPrimitiveNode::type() const +{ + return RootPrimitiveNodeType; +} + +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h index 519b40aaf..0b7cd8b4e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitive_item.h @@ -1,200 +1,200 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PRIMITIVE_ITEM_H -#define PRIMITIVE_ITEM_H - -// Project includes - -// NeL includes -#include -#include - -// Qt includes -#include -#include -#include - -namespace WorldEditor -{ -class RootPrimitiveNode; - -/* -@class Node -@brief -@details -*/ -class Node -{ -public: - - enum NodeType - { - BasicNodeType, - WorldEditNodeType, - RootPrimitiveNodeType, - LandscapeNodeType, - PrimitiveNodeType, - UserNodeType = 1024 - }; - - Node(); - virtual ~Node(); - - /// Remove child node from the child list. - void removeChildNode(Node *node); - - /// Insert node at the beginning of the list. - void prependChildNode(Node *node); - - /// Insert node at the end of the list. - void appendChildNode(Node *node); - - /// Insert node in front of the node pointed to by the pointer before. - void insertChildNodeBefore(Node *node, Node *before); - - /// Insert node in back of the node pointed to by the pointer after. - void insertChildNodeAfter(Node *node, Node *after); - - /// Insert node in pos - void insertChildNode(int pos, Node *node); - - /// Return the node at index position row in the child list. - Node *child(int row); - - /// Return the number of nodes in the list. - int childCount() const; - - /// Return a row index this node. - int row() const; - - /// Return a pointer to this node's parent item. If this node does not have a parent, 0 is returned. - Node *parent(); - - /// Set this node's custom data for the key key to value. - void setData(int key, const QVariant &data); - - /// Return this node's custom data for the key key as a QVariant. - QVariant data(int key) const; - - /// Return a type this node. - virtual NodeType type() const; - -private: - Q_DISABLE_COPY(Node) - - Node *m_parent; - QList m_children; - QHash m_data; -}; - -/* -@class WorldEditNode -@brief -@details -*/ -class WorldEditNode: public Node -{ -public: - WorldEditNode(const QString &name); - virtual ~WorldEditNode(); - - void setContext(const QString &name); - QString context() const; - void setDataPath(const QString &path); - QString dataPath() const; - - virtual NodeType type() const; - -private: - QString m_context; - QString m_dataPath; -}; - -/* -@class LandscapeNode -@brief -@details -*/ -class LandscapeNode: public Node -{ -public: - LandscapeNode(const QString &name, int id); - virtual ~LandscapeNode(); - - int id() const; - QString fileName() const; - - virtual NodeType type() const; - -private: - - QString m_fileName; - int m_id; -}; - -/* -@class PrimitiveNode -@brief -@details -*/ -class PrimitiveNode: public Node -{ -public: - explicit PrimitiveNode(NLLIGO::IPrimitive *primitive); - virtual ~PrimitiveNode(); - - NLLIGO::IPrimitive *primitive() const; - const NLLIGO::CPrimitiveClass *primitiveClass() const; - RootPrimitiveNode *rootPrimitiveNode(); - - virtual NodeType type() const; - -private: - NLLIGO::IPrimitive *m_primitive; -}; - -/* -@class RootPrimitiveNode -@brief -@details -*/ -class RootPrimitiveNode: public PrimitiveNode -{ -public: - RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives); - virtual ~RootPrimitiveNode(); - - NLLIGO::CPrimitives *primitives() const; - - void setFileName(const QString &fileName); - QString fileName() const; - virtual NodeType type() const; - -private: - - QString m_fileName; - NLLIGO::CPrimitives *m_primitives; -}; - -typedef QList NodeList; - -} /* namespace WorldEditor */ - -// Enable the use of QVariant with this class. -Q_DECLARE_METATYPE(WorldEditor::Node *) - -#endif // PRIMITIVE_ITEM_H +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PRIMITIVE_ITEM_H +#define PRIMITIVE_ITEM_H + +// Project includes + +// NeL includes +#include +#include + +// Qt includes +#include +#include +#include + +namespace WorldEditor +{ +class RootPrimitiveNode; + +/* +@class Node +@brief +@details +*/ +class Node +{ +public: + + enum NodeType + { + BasicNodeType, + WorldEditNodeType, + RootPrimitiveNodeType, + LandscapeNodeType, + PrimitiveNodeType, + UserNodeType = 1024 + }; + + Node(); + virtual ~Node(); + + /// Remove child node from the child list. + void removeChildNode(Node *node); + + /// Insert node at the beginning of the list. + void prependChildNode(Node *node); + + /// Insert node at the end of the list. + void appendChildNode(Node *node); + + /// Insert node in front of the node pointed to by the pointer before. + void insertChildNodeBefore(Node *node, Node *before); + + /// Insert node in back of the node pointed to by the pointer after. + void insertChildNodeAfter(Node *node, Node *after); + + /// Insert node in pos + void insertChildNode(int pos, Node *node); + + /// Return the node at index position row in the child list. + Node *child(int row); + + /// Return the number of nodes in the list. + int childCount() const; + + /// Return a row index this node. + int row() const; + + /// Return a pointer to this node's parent item. If this node does not have a parent, 0 is returned. + Node *parent(); + + /// Set this node's custom data for the key key to value. + void setData(int key, const QVariant &data); + + /// Return this node's custom data for the key key as a QVariant. + QVariant data(int key) const; + + /// Return a type this node. + virtual NodeType type() const; + +private: + Q_DISABLE_COPY(Node) + + Node *m_parent; + QList m_children; + QHash m_data; +}; + +/* +@class WorldEditNode +@brief +@details +*/ +class WorldEditNode: public Node +{ +public: + WorldEditNode(const QString &name); + virtual ~WorldEditNode(); + + void setContext(const QString &name); + QString context() const; + void setDataPath(const QString &path); + QString dataPath() const; + + virtual NodeType type() const; + +private: + QString m_context; + QString m_dataPath; +}; + +/* +@class LandscapeNode +@brief +@details +*/ +class LandscapeNode: public Node +{ +public: + LandscapeNode(const QString &name, int id); + virtual ~LandscapeNode(); + + int id() const; + QString fileName() const; + + virtual NodeType type() const; + +private: + + QString m_fileName; + int m_id; +}; + +/* +@class PrimitiveNode +@brief +@details +*/ +class PrimitiveNode: public Node +{ +public: + explicit PrimitiveNode(NLLIGO::IPrimitive *primitive); + virtual ~PrimitiveNode(); + + NLLIGO::IPrimitive *primitive() const; + const NLLIGO::CPrimitiveClass *primitiveClass() const; + RootPrimitiveNode *rootPrimitiveNode(); + + virtual NodeType type() const; + +private: + NLLIGO::IPrimitive *m_primitive; +}; + +/* +@class RootPrimitiveNode +@brief +@details +*/ +class RootPrimitiveNode: public PrimitiveNode +{ +public: + RootPrimitiveNode(const QString &name, NLLIGO::CPrimitives *primitives); + virtual ~RootPrimitiveNode(); + + NLLIGO::CPrimitives *primitives() const; + + void setFileName(const QString &fileName); + QString fileName() const; + virtual NodeType type() const; + +private: + + QString m_fileName; + NLLIGO::CPrimitives *m_primitives; +}; + +typedef QList NodeList; + +} /* namespace WorldEditor */ + +// Enable the use of QVariant with this class. +Q_DECLARE_METATYPE(WorldEditor::Node *) + +#endif // PRIMITIVE_ITEM_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp index 78313624e..db8a7f44b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.cpp @@ -1,328 +1,328 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "primitive_item.h" -#include "primitives_model.h" -#include "world_editor_misc.h" -#include "world_editor_constants.h" - -// NeL includes -#include -#include -#include - -// Qt includes -#include - -namespace WorldEditor -{ - -PrimitivesTreeModel::PrimitivesTreeModel(QObject *parent) - : QAbstractItemModel(parent), - m_worldEditNode(0) -{ - m_rootNode = new Node(); - m_rootNode->setData(Qt::DisplayRole, "Name"); -} - -PrimitivesTreeModel::~PrimitivesTreeModel() -{ - delete m_rootNode; -} - -int PrimitivesTreeModel::columnCount(const QModelIndex &parent) const -{ - /* if (parent.isValid()) - return static_cast(parent.internalPointer())->columnCount(); - else - return m_rootItem->columnCount(); - */ - return 1; -} - -QVariant PrimitivesTreeModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - Node *item = static_cast(index.internalPointer()); - switch (role) - { -// case Qt::TextAlignmentRole: -// return int(Qt::AlignLeft | Qt::AlignVCenter); - case Qt::DisplayRole: - return item->data(Qt::DisplayRole); - case Qt::DecorationRole: - return item->data(Qt::DecorationRole); - default: - return QVariant(); - } -} - -Qt::ItemFlags PrimitivesTreeModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; -} - -QVariant PrimitivesTreeModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) -// return m_rootNode->data(section); - return m_rootNode->data(Qt::DisplayRole); - - return QVariant(); -} - -QModelIndex PrimitivesTreeModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - Node *parentNode; - - if (!parent.isValid()) - parentNode = m_rootNode; - else - parentNode = static_cast(parent.internalPointer()); - - Node *childNode = parentNode->child(row); - if (childNode) - return createIndex(row, column, childNode); - else - return QModelIndex(); -} - -QModelIndex PrimitivesTreeModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - Node *childNode = static_cast(index.internalPointer()); - Node *parentNode = childNode->parent(); - - if (parentNode == m_rootNode) - return QModelIndex(); - - return createIndex(parentNode->row(), 0, parentNode); -} - -int PrimitivesTreeModel::rowCount(const QModelIndex &parent) const -{ - Node *parentNode; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentNode = m_rootNode; - else - parentNode = static_cast(parent.internalPointer()); - - return parentNode->childCount(); -} - -Path PrimitivesTreeModel::pathFromIndex(const QModelIndex &index) -{ - QModelIndex iter = index; - Path path; - while(iter.isValid()) - { - path.prepend(PathItem(iter.row(), iter.column())); - iter = iter.parent(); - } - return path; -} - -Path PrimitivesTreeModel::pathFromNode(Node *node) -{ - Node *iter = node; - Path path; - while(iter != 0) - { - path.prepend(PathItem(iter->row(), 0)); - iter = iter->parent(); - } - return path; -} - -QModelIndex PrimitivesTreeModel::pathToIndex(const Path &path) -{ - QModelIndex iter; - for(int i = 0; i < path.size(); i++) - { - iter = index(path[i].first, path[i].second, iter); - } - return iter; -} - -Node *PrimitivesTreeModel::pathToNode(const Path &path) -{ - Node *node = m_rootNode; - for(int i = 1; i < path.size(); i++) - { - node = node->child(path[i].first); - } - return node; -} - -void PrimitivesTreeModel::createWorldEditNode(const QString &fileName) -{ - // World edit node already is created, if yes is showing error message box - if (m_worldEditNode != 0) - nlerror("World edit node already is created."); - - beginResetModel(); - m_worldEditNode = new WorldEditNode(fileName); - m_rootNode->appendChildNode(m_worldEditNode); - endResetModel(); -} - -void PrimitivesTreeModel::deleteWorldEditNode() -{ - beginResetModel(); - if (m_worldEditNode != 0) - { - delete m_worldEditNode; - m_worldEditNode = 0; - } - endResetModel(); -} - -bool PrimitivesTreeModel::isWorldEditNodeLoaded() const -{ - if (m_worldEditNode == 0) - return false; - else - return true; -} - -Path PrimitivesTreeModel::createLandscapeNode(const QString &fileName, int id, int pos) -{ - if (m_worldEditNode == 0) - createWorldEditNode("NewWorldEdit"); - - QModelIndex parentIndex = index(0, 0, QModelIndex()); - int insPos = pos; - if (pos == -1) - insPos = 0; - - beginInsertRows(parentIndex, insPos, insPos); - LandscapeNode *newNode = new LandscapeNode(fileName, id); - m_worldEditNode->insertChildNode(insPos, newNode); - endInsertRows(); - return pathFromIndex(index(0, 0, index(insPos, 0, QModelIndex()))); -} - - -Path PrimitivesTreeModel::createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives, int pos) -{ - if (m_worldEditNode == 0) - createWorldEditNode("NewWorldEdit"); - - QString name = "NewPrimitive"; - if (!fileName.isEmpty()) - name = fileName; - - int insPos = pos; - - // Get position - if (pos == AtTheEnd) - insPos = m_worldEditNode->childCount(); - - QModelIndex parentIndex = index(0, 0, QModelIndex()); - - // Add root node in tree model - beginInsertRows(parentIndex, insPos, insPos); - RootPrimitiveNode *newNode = new RootPrimitiveNode(name, primitives); - m_worldEditNode->insertChildNode(insPos, newNode); - endInsertRows(); - - newNode->setData(Constants::PRIMITIVE_FILE_IS_CREATED, !fileName.isEmpty()); - newNode->setData(Constants::PRIMITIVE_IS_MODIFIED, false); - - QModelIndex rootPrimIndex = index(insPos, 0, parentIndex); - - // Scan childs items and add in the tree model - for (uint i = 0; i < primitives->RootNode->getNumChildren(); ++i) - { - NLLIGO::IPrimitive *childPrim; - primitives->RootNode->getChild(childPrim, i); - createChildNodes(childPrim, i, rootPrimIndex); - } - - return pathFromIndex(rootPrimIndex); -} - -Path PrimitivesTreeModel::createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent, int pos) -{ - QModelIndex parentIndex = pathToIndex(parent); - Node *parentNode = static_cast(parentIndex.internalPointer()); - - int insPos = pos; - if (pos == AtTheEnd) - insPos = parentNode->childCount(); - - createChildNodes(primitive, insPos, parentIndex); - - return pathFromIndex(index(insPos, 0, parentIndex)); -} - -void PrimitivesTreeModel::deleteNode(const Path &path) -{ - QModelIndex nodeIndex = pathToIndex(path); - QModelIndex parentIndex = nodeIndex.parent(); - Node *node = static_cast(nodeIndex.internalPointer()); - - // Scan childs items and delete from the tree model - removeChildNodes(node, parentIndex); -} - -void PrimitivesTreeModel::createChildNodes(NLLIGO::IPrimitive *primitive, int pos, const QModelIndex &parent) -{ - Node *parentNode = static_cast(parent.internalPointer()); - - // Add node in the tree model - beginInsertRows(parent, pos, pos); - PrimitiveNode *newNode = new PrimitiveNode(primitive); - parentNode->insertChildNode(pos, newNode); - endInsertRows(); - - // Scan childs items and add in the tree model - QModelIndex childIndex = index(pos, 0, parent); - for (uint i = 0; i < primitive->getNumChildren(); ++i) - { - NLLIGO::IPrimitive *childPrim; - primitive->getChild(childPrim, i); - createChildNodes(childPrim, i, childIndex); - } -} - -void PrimitivesTreeModel::removeChildNodes(Node *node, const QModelIndex &parent) -{ - // Delete all child nodes from the tree model - while (node->childCount() != 0) - removeChildNodes(node->child(node->childCount() - 1), parent.child(node->row(), 0)); - - // Delete node from the tree model - beginRemoveRows(parent, node->row(), node->row()); - delete node; - endRemoveRows(); -} - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "primitive_item.h" +#include "primitives_model.h" +#include "world_editor_misc.h" +#include "world_editor_constants.h" + +// NeL includes +#include +#include +#include + +// Qt includes +#include + +namespace WorldEditor +{ + +PrimitivesTreeModel::PrimitivesTreeModel(QObject *parent) + : QAbstractItemModel(parent), + m_worldEditNode(0) +{ + m_rootNode = new Node(); + m_rootNode->setData(Qt::DisplayRole, "Name"); +} + +PrimitivesTreeModel::~PrimitivesTreeModel() +{ + delete m_rootNode; +} + +int PrimitivesTreeModel::columnCount(const QModelIndex &parent) const +{ + /* if (parent.isValid()) + return static_cast(parent.internalPointer())->columnCount(); + else + return m_rootItem->columnCount(); + */ + return 1; +} + +QVariant PrimitivesTreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + Node *item = static_cast(index.internalPointer()); + switch (role) + { +// case Qt::TextAlignmentRole: +// return int(Qt::AlignLeft | Qt::AlignVCenter); + case Qt::DisplayRole: + return item->data(Qt::DisplayRole); + case Qt::DecorationRole: + return item->data(Qt::DecorationRole); + default: + return QVariant(); + } +} + +Qt::ItemFlags PrimitivesTreeModel::flags(const QModelIndex &index) const +{ + if (!index.isValid()) + return 0; + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant PrimitivesTreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) +// return m_rootNode->data(section); + return m_rootNode->data(Qt::DisplayRole); + + return QVariant(); +} + +QModelIndex PrimitivesTreeModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + Node *parentNode; + + if (!parent.isValid()) + parentNode = m_rootNode; + else + parentNode = static_cast(parent.internalPointer()); + + Node *childNode = parentNode->child(row); + if (childNode) + return createIndex(row, column, childNode); + else + return QModelIndex(); +} + +QModelIndex PrimitivesTreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + Node *childNode = static_cast(index.internalPointer()); + Node *parentNode = childNode->parent(); + + if (parentNode == m_rootNode) + return QModelIndex(); + + return createIndex(parentNode->row(), 0, parentNode); +} + +int PrimitivesTreeModel::rowCount(const QModelIndex &parent) const +{ + Node *parentNode; + if (parent.column() > 0) + return 0; + + if (!parent.isValid()) + parentNode = m_rootNode; + else + parentNode = static_cast(parent.internalPointer()); + + return parentNode->childCount(); +} + +Path PrimitivesTreeModel::pathFromIndex(const QModelIndex &index) +{ + QModelIndex iter = index; + Path path; + while(iter.isValid()) + { + path.prepend(PathItem(iter.row(), iter.column())); + iter = iter.parent(); + } + return path; +} + +Path PrimitivesTreeModel::pathFromNode(Node *node) +{ + Node *iter = node; + Path path; + while(iter != 0) + { + path.prepend(PathItem(iter->row(), 0)); + iter = iter->parent(); + } + return path; +} + +QModelIndex PrimitivesTreeModel::pathToIndex(const Path &path) +{ + QModelIndex iter; + for(int i = 0; i < path.size(); i++) + { + iter = index(path[i].first, path[i].second, iter); + } + return iter; +} + +Node *PrimitivesTreeModel::pathToNode(const Path &path) +{ + Node *node = m_rootNode; + for(int i = 1; i < path.size(); i++) + { + node = node->child(path[i].first); + } + return node; +} + +void PrimitivesTreeModel::createWorldEditNode(const QString &fileName) +{ + // World edit node already is created, if yes is showing error message box + if (m_worldEditNode != 0) + nlerror("World edit node already is created."); + + beginResetModel(); + m_worldEditNode = new WorldEditNode(fileName); + m_rootNode->appendChildNode(m_worldEditNode); + endResetModel(); +} + +void PrimitivesTreeModel::deleteWorldEditNode() +{ + beginResetModel(); + if (m_worldEditNode != 0) + { + delete m_worldEditNode; + m_worldEditNode = 0; + } + endResetModel(); +} + +bool PrimitivesTreeModel::isWorldEditNodeLoaded() const +{ + if (m_worldEditNode == 0) + return false; + else + return true; +} + +Path PrimitivesTreeModel::createLandscapeNode(const QString &fileName, int id, int pos) +{ + if (m_worldEditNode == 0) + createWorldEditNode("NewWorldEdit"); + + QModelIndex parentIndex = index(0, 0, QModelIndex()); + int insPos = pos; + if (pos == -1) + insPos = 0; + + beginInsertRows(parentIndex, insPos, insPos); + LandscapeNode *newNode = new LandscapeNode(fileName, id); + m_worldEditNode->insertChildNode(insPos, newNode); + endInsertRows(); + return pathFromIndex(index(0, 0, index(insPos, 0, QModelIndex()))); +} + + +Path PrimitivesTreeModel::createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives, int pos) +{ + if (m_worldEditNode == 0) + createWorldEditNode("NewWorldEdit"); + + QString name = "NewPrimitive"; + if (!fileName.isEmpty()) + name = fileName; + + int insPos = pos; + + // Get position + if (pos == AtTheEnd) + insPos = m_worldEditNode->childCount(); + + QModelIndex parentIndex = index(0, 0, QModelIndex()); + + // Add root node in tree model + beginInsertRows(parentIndex, insPos, insPos); + RootPrimitiveNode *newNode = new RootPrimitiveNode(name, primitives); + m_worldEditNode->insertChildNode(insPos, newNode); + endInsertRows(); + + newNode->setData(Constants::PRIMITIVE_FILE_IS_CREATED, !fileName.isEmpty()); + newNode->setData(Constants::PRIMITIVE_IS_MODIFIED, false); + + QModelIndex rootPrimIndex = index(insPos, 0, parentIndex); + + // Scan childs items and add in the tree model + for (uint i = 0; i < primitives->RootNode->getNumChildren(); ++i) + { + NLLIGO::IPrimitive *childPrim; + primitives->RootNode->getChild(childPrim, i); + createChildNodes(childPrim, i, rootPrimIndex); + } + + return pathFromIndex(rootPrimIndex); +} + +Path PrimitivesTreeModel::createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent, int pos) +{ + QModelIndex parentIndex = pathToIndex(parent); + Node *parentNode = static_cast(parentIndex.internalPointer()); + + int insPos = pos; + if (pos == AtTheEnd) + insPos = parentNode->childCount(); + + createChildNodes(primitive, insPos, parentIndex); + + return pathFromIndex(index(insPos, 0, parentIndex)); +} + +void PrimitivesTreeModel::deleteNode(const Path &path) +{ + QModelIndex nodeIndex = pathToIndex(path); + QModelIndex parentIndex = nodeIndex.parent(); + Node *node = static_cast(nodeIndex.internalPointer()); + + // Scan childs items and delete from the tree model + removeChildNodes(node, parentIndex); +} + +void PrimitivesTreeModel::createChildNodes(NLLIGO::IPrimitive *primitive, int pos, const QModelIndex &parent) +{ + Node *parentNode = static_cast(parent.internalPointer()); + + // Add node in the tree model + beginInsertRows(parent, pos, pos); + PrimitiveNode *newNode = new PrimitiveNode(primitive); + parentNode->insertChildNode(pos, newNode); + endInsertRows(); + + // Scan childs items and add in the tree model + QModelIndex childIndex = index(pos, 0, parent); + for (uint i = 0; i < primitive->getNumChildren(); ++i) + { + NLLIGO::IPrimitive *childPrim; + primitive->getChild(childPrim, i); + createChildNodes(childPrim, i, childIndex); + } +} + +void PrimitivesTreeModel::removeChildNodes(Node *node, const QModelIndex &parent) +{ + // Delete all child nodes from the tree model + while (node->childCount() != 0) + removeChildNodes(node->child(node->childCount() - 1), parent.child(node->row(), 0)); + + // Delete node from the tree model + beginRemoveRows(parent, node->row(), node->row()); + delete node; + endRemoveRows(); +} + } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h index 031317d0c..cd01532dd 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_model.h @@ -1,104 +1,104 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef PRIMITIVES_MODEL_H -#define PRIMITIVES_MODEL_H - -// NeL includes -#include -#include -#include -#include - -// Qt includes -#include -#include -#include - -namespace WorldEditor -{ -class Node; -class WorldEditNode; - -const int AtTheEnd = -1; - -typedef QPair PathItem; -/* -@typedef Path -@brief It store a list of row and column numbers which have to walk through from the root index of the model to reach the need item. -It is used for undo/redo commands. -*/ -typedef QList Path; - -/** -@class PrimitivesTreeModel -@brief -@details -*/ -class PrimitivesTreeModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - explicit PrimitivesTreeModel(QObject *parent = 0); - ~PrimitivesTreeModel(); - - QVariant data(const QModelIndex &index, int role) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const; - QModelIndex parent(const QModelIndex &index) const; - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - - /// Convert QModelIndex to the persistent index - @Path. - /// @Path is a list of [row,column] pairs showing us the way through the model. - Path pathFromIndex(const QModelIndex &index); - QModelIndex pathToIndex(const Path &path); - - Path pathFromNode(Node *node); - Node *pathToNode(const Path &path); - - void createWorldEditNode(const QString &fileName); - void deleteWorldEditNode(); - bool isWorldEditNodeLoaded() const; - - /// Add new landscape node in tree model. - Path createLandscapeNode(const QString &fileName, int id, int pos = AtTheEnd); - - /// Add new root primitive node and all sub-primitives in the tree model. - Path createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives, int pos = AtTheEnd); - - /// Add new primitive node and all sub-primitives in the tree model. - Path createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent, int pos = AtTheEnd); - - /// Delete node and all child nodes from the tree model - void deleteNode(const Path &path); - -private: - void createChildNodes(NLLIGO::IPrimitive *primitive, int pos, const QModelIndex &parent); - void removeChildNodes(Node *node, const QModelIndex &parent); - - Node *m_rootNode; - WorldEditNode *m_worldEditNode; -}; - -} /* namespace WorldEditor */ - -#endif // PRIMITIVES_MODEL_H +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PRIMITIVES_MODEL_H +#define PRIMITIVES_MODEL_H + +// NeL includes +#include +#include +#include +#include + +// Qt includes +#include +#include +#include + +namespace WorldEditor +{ +class Node; +class WorldEditNode; + +const int AtTheEnd = -1; + +typedef QPair PathItem; +/* +@typedef Path +@brief It store a list of row and column numbers which have to walk through from the root index of the model to reach the need item. +It is used for undo/redo commands. +*/ +typedef QList Path; + +/** +@class PrimitivesTreeModel +@brief +@details +*/ +class PrimitivesTreeModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit PrimitivesTreeModel(QObject *parent = 0); + ~PrimitivesTreeModel(); + + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + + /// Convert QModelIndex to the persistent index - @Path. + /// @Path is a list of [row,column] pairs showing us the way through the model. + Path pathFromIndex(const QModelIndex &index); + QModelIndex pathToIndex(const Path &path); + + Path pathFromNode(Node *node); + Node *pathToNode(const Path &path); + + void createWorldEditNode(const QString &fileName); + void deleteWorldEditNode(); + bool isWorldEditNodeLoaded() const; + + /// Add new landscape node in tree model. + Path createLandscapeNode(const QString &fileName, int id, int pos = AtTheEnd); + + /// Add new root primitive node and all sub-primitives in the tree model. + Path createRootPrimitiveNode(const QString &fileName, NLLIGO::CPrimitives *primitives, int pos = AtTheEnd); + + /// Add new primitive node and all sub-primitives in the tree model. + Path createPrimitiveNode(NLLIGO::IPrimitive *primitive, const Path &parent, int pos = AtTheEnd); + + /// Delete node and all child nodes from the tree model + void deleteNode(const Path &path); + +private: + void createChildNodes(NLLIGO::IPrimitive *primitive, int pos, const QModelIndex &parent); + void removeChildNodes(Node *node, const QModelIndex &parent); + + Node *m_rootNode; + WorldEditNode *m_worldEditNode; +}; + +} /* namespace WorldEditor */ + +#endif // PRIMITIVES_MODEL_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp index e27e824b4..33b98eed6 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.cpp @@ -1,458 +1,458 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "primitives_view.h" -#include "primitives_model.h" -#include "world_editor_actions.h" -#include "world_editor_constants.h" - -#include "../core/core_constants.h" -#include "../landscape_editor/landscape_editor_constants.h" -#include "../landscape_editor/builder_zone_base.h" - -// NeL includes -#include -#include -#include -#include - -// Qt includes -#include -#include -#include -#include -#include - -namespace WorldEditor -{ - -PrimitivesView::PrimitivesView(QWidget *parent) - : QTreeView(parent), - m_undoStack(0), - m_worldEditorScene(0), - m_zoneBuilder(0), - m_primitivesTreeModel(0) -{ - setContextMenuPolicy(Qt::DefaultContextMenu); - - m_unloadAction = new QAction("Unload", this); - - m_saveAction = new QAction("Save", this); - m_saveAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); - - m_saveAsAction = new QAction("Save As...", this); - m_saveAsAction->setIcon(QIcon(Core::Constants::ICON_SAVE_AS)); - - m_loadLandAction = new QAction("Load landscape file", this); - m_loadLandAction->setIcon(QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM)); - - m_loadPrimitiveAction = new QAction("Load primitive file", this); - m_loadPrimitiveAction->setIcon(QIcon(Constants::ICON_ROOT_PRIMITIVE)); - - m_newPrimitiveAction = new QAction("New primitive", this); - - m_deleteAction = new QAction("Delete", this); - - m_selectChildrenAction = new QAction("Select children", this); - - m_helpAction = new QAction("Help", this); - m_helpAction->setEnabled(false); - - m_showAction = new QAction("Show", this); - m_showAction->setEnabled(false); - - m_hideAction = new QAction("Hide", this); - m_hideAction->setEnabled(false); - - connect(m_loadLandAction, SIGNAL(triggered()), this, SLOT(loadLandscape())); - connect(m_loadPrimitiveAction, SIGNAL(triggered()), this, SLOT(loadRootPrimitive())); - connect(m_newPrimitiveAction, SIGNAL(triggered()), this, SLOT(createRootPrimitive())); - connect(m_selectChildrenAction, SIGNAL(triggered()), this, SLOT(selectChildren())); - connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deletePrimitives())); - connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); - connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); - connect(m_unloadAction, SIGNAL(triggered()), this, SLOT(unload())); - connect(m_showAction, SIGNAL(triggered()), this, SLOT(showPrimitive())); - connect(m_hideAction, SIGNAL(triggered()), this, SLOT(hidePrimitive())); - -#ifdef Q_OS_DARWIN - setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); -#endif -} - -PrimitivesView::~PrimitivesView() -{ -} - -void PrimitivesView::setUndoStack(QUndoStack *undoStack) -{ - m_undoStack = undoStack; -} - -void PrimitivesView::setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder) -{ - m_zoneBuilder = zoneBuilder; -} - -void PrimitivesView::setWorldScene(WorldEditorScene *worldEditorScene) -{ - m_worldEditorScene = worldEditorScene; -} - -void PrimitivesView::setModel(PrimitivesTreeModel *model) -{ - QTreeView::setModel(model); - m_primitivesTreeModel = model; -} - -void PrimitivesView::loadRootPrimitive() -{ - nlassert(m_undoStack); - nlassert(m_primitivesTreeModel); - - QStringList fileNames = QFileDialog::getOpenFileNames(this, - tr("Open NeL Ligo primitive file"), m_lastDir, - tr("All NeL Ligo primitive files (*.primitive)")); - - setCursor(Qt::WaitCursor); - if (!fileNames.isEmpty()) - { - if (fileNames.count() > 1) - m_undoStack->beginMacro(tr("Load primitive files")); - - Q_FOREACH(QString fileName, fileNames) - { - m_lastDir = QFileInfo(fileName).absolutePath(); - m_undoStack->push(new LoadRootPrimitiveCommand(fileName, m_worldEditorScene, m_primitivesTreeModel, this)); - } - - if (fileNames.count() > 1) - m_undoStack->endMacro(); - } - setCursor(Qt::ArrowCursor); -} - -void PrimitivesView::loadLandscape() -{ - nlassert(m_undoStack); - nlassert(m_zoneBuilder); - nlassert(m_primitivesTreeModel); - - QStringList fileNames = QFileDialog::getOpenFileNames(this, - tr("Open NeL Ligo land file"), m_lastDir, - tr("All NeL Ligo land files (*.land)")); - - setCursor(Qt::WaitCursor); - if (!fileNames.isEmpty()) - { - if (fileNames.count() > 1) - m_undoStack->beginMacro(tr("Load land files")); - - Q_FOREACH(QString fileName, fileNames) - { - m_lastDir = QFileInfo(fileName).absolutePath(); - m_undoStack->push(new LoadLandscapeCommand(fileName, m_primitivesTreeModel, m_zoneBuilder)); - } - - if (fileNames.count() > 1) - m_undoStack->endMacro(); - } - setCursor(Qt::ArrowCursor); -} - -void PrimitivesView::createRootPrimitive() -{ - nlassert(m_undoStack); - nlassert(m_primitivesTreeModel); - - m_undoStack->push(new CreateRootPrimitiveCommand("NewPrimitive", m_primitivesTreeModel)); -} - -void PrimitivesView::selectChildren() -{ - QModelIndexList indexList = selectionModel()->selectedRows(); - QModelIndex parentIndex = indexList.first(); - - selectionModel()->clearSelection(); - - QItemSelection itemSelection; - selectChildren(parentIndex, itemSelection); - selectionModel()->select(itemSelection, QItemSelectionModel::Select); -} - -void PrimitivesView::save() -{ - nlassert(m_primitivesTreeModel); - - QModelIndexList indexList = selectionModel()->selectedRows(); - QModelIndex index = indexList.first(); - - RootPrimitiveNode *node = static_cast(index.internalPointer()); - - if (node->data(Constants::PRIMITIVE_FILE_IS_CREATED).toBool()) - { - if (!NLLIGO::saveXmlPrimitiveFile(*node->primitives(), node->fileName().toStdString())) - QMessageBox::warning(this, "World Editor Qt", tr("Error writing output file: %1").arg(node->fileName())); - else - node->setData(Constants::PRIMITIVE_IS_MODIFIED, false); - } - else - saveAs(); -} - -void PrimitivesView::saveAs() -{ - nlassert(m_primitivesTreeModel); - - QString fileName = QFileDialog::getSaveFileName(this, - tr("Save NeL Ligo primitive file"), m_lastDir, - tr("NeL Ligo primitive file (*.primitive)")); - - setCursor(Qt::WaitCursor); - if (!fileName.isEmpty()) - { - QModelIndexList indexList = selectionModel()->selectedRows(); - QModelIndex index = indexList.first(); - - RootPrimitiveNode *node = static_cast(index.internalPointer()); - - if (!NLLIGO::saveXmlPrimitiveFile(*node->primitives(), fileName.toStdString())) - QMessageBox::warning(this, "World Editor Qt", tr("Error writing output file: %1").arg(fileName)); - else - { - node->setFileName(fileName); - node->setData(Constants::PRIMITIVE_FILE_IS_CREATED, true); - node->setData(Constants::PRIMITIVE_IS_MODIFIED, false); - } - } - setCursor(Qt::ArrowCursor); -} - -void PrimitivesView::deletePrimitives() -{ - nlassert(m_undoStack); - nlassert(m_primitivesTreeModel); - - QModelIndexList indexList = selectionModel()->selectedRows(); - - QModelIndex index = indexList.first(); - - PrimitiveNode *node = static_cast(index.internalPointer()); - - if (node->primitiveClass()->Deletable) - m_undoStack->push(new DeletePrimitiveCommand(index, m_primitivesTreeModel, m_worldEditorScene, this)); - -} - -void PrimitivesView::unload() -{ - nlassert(m_undoStack); - nlassert(m_primitivesTreeModel); - - QModelIndexList indexList = selectionModel()->selectedRows(); - QModelIndex index = indexList.first(); - Node *node = static_cast(index.internalPointer()); - switch (node->type()) - { - case Node::WorldEditNodeType: - { - break; - } - case Node::LandscapeNodeType: - { - m_undoStack->push(new UnloadLandscapeCommand(index, m_primitivesTreeModel, m_zoneBuilder)); - break; - } - case Node::RootPrimitiveNodeType: - { - m_undoStack->push(new UnloadRootPrimitiveCommand(index, m_worldEditorScene, m_primitivesTreeModel, this)); - break; - } - } -} - -void PrimitivesView::showPrimitive() -{ -} - -void PrimitivesView::hidePrimitive() -{ -} - -void PrimitivesView::addNewPrimitiveByClass(int value) -{ - nlassert(m_undoStack); - nlassert(m_primitivesTreeModel); - - QModelIndexList indexList = selectionModel()->selectedRows(); - - PrimitiveNode *node = static_cast(indexList.first().internalPointer()); - - // Get class name - QString className = node->primitiveClass()->DynamicChildren[value].ClassName.c_str(); - - m_undoStack->push(new AddPrimitiveByClassCommand(className, m_primitivesTreeModel->pathFromIndex(indexList.first()), - m_worldEditorScene, m_primitivesTreeModel, this)); -} - -void PrimitivesView::generatePrimitives(int value) -{ -} - -void PrimitivesView::openItem(int value) -{ -} - -void PrimitivesView::contextMenuEvent(QContextMenuEvent *event) -{ - QWidget::contextMenuEvent(event); - QModelIndexList indexList = selectionModel()->selectedRows(); - if (indexList.size() == 0) - return; - - QMenu *popurMenu = new QMenu(this); - - if (indexList.size() == 1) - { - Node *node = static_cast(indexList.first().internalPointer()); - switch (node->type()) - { - case Node::WorldEditNodeType: - fillMenu_WorldEdit(popurMenu); - break; - case Node::RootPrimitiveNodeType: - fillMenu_RootPrimitive(popurMenu, indexList.first()); - break; - case Node::LandscapeNodeType: - fillMenu_Landscape(popurMenu); - break; - case Node::PrimitiveNodeType: - fillMenu_Primitive(popurMenu, indexList.first()); - break; - }; - } - - popurMenu->exec(event->globalPos()); - delete popurMenu; - event->accept(); -} - -void PrimitivesView::selectChildren(const QModelIndex &parent, QItemSelection &itemSelection) -{ - const int rowCount = model()->rowCount(parent); - - QItemSelection mergeItemSelection(parent.child(0, 0), parent.child(rowCount - 1, 0)); - itemSelection.merge(mergeItemSelection, QItemSelectionModel::Select); - - for (int i = 0; i < rowCount; ++i) - { - QModelIndex childIndex = parent.child(i, 0); - if (model()->rowCount(childIndex) != 0) - selectChildren(childIndex, itemSelection); - } -} - -void PrimitivesView::fillMenu_WorldEdit(QMenu *menu) -{ - //menu->addAction(m_unloadAction); - //menu->addAction(m_saveAction); - //menu->addAction(m_saveAsAction); - menu->addSeparator(); - menu->addAction(m_loadLandAction); - menu->addAction(m_loadPrimitiveAction); - menu->addAction(m_newPrimitiveAction); - menu->addSeparator(); - menu->addAction(m_helpAction); -} - -void PrimitivesView::fillMenu_Landscape(QMenu *menu) -{ - menu->addAction(m_unloadAction); - menu->addSeparator(); - menu->addAction(m_showAction); - menu->addAction(m_hideAction); -} - -void PrimitivesView::fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index) -{ - menu->addAction(m_saveAction); - menu->addAction(m_saveAsAction); - menu->addAction(m_unloadAction); - fillMenu_Primitive(menu, index); - menu->removeAction(m_deleteAction); -} - -void PrimitivesView::fillMenu_Primitive(QMenu *menu, const QModelIndex &index) -{ - menu->addAction(m_deleteAction); - menu->addAction(m_selectChildrenAction); - menu->addAction(m_helpAction); - menu->addSeparator(); - menu->addAction(m_showAction); - menu->addAction(m_hideAction); - - QSignalMapper *addSignalMapper = new QSignalMapper(menu); - QSignalMapper *generateSignalMapper = new QSignalMapper(menu); - //QSignalMapper *openSignalMapper = new QSignalMapper(menu); - connect(addSignalMapper, SIGNAL(mapped(int)), this, SLOT(addNewPrimitiveByClass(int))); - connect(generateSignalMapper, SIGNAL(mapped(int)), this, SLOT(generatePrimitives(int))); - //connect(openSignalMapper, SIGNAL(mapped(int)), this, SLOT(openItem(int))); - - PrimitiveNode *node = static_cast(index.internalPointer()); - const NLLIGO::CPrimitiveClass *primClass = node->primitiveClass(); - - // What class is it ? - if (primClass && primClass->DynamicChildren.size()) - { - menu->addSeparator(); - - // For each child, add a create method - for (size_t i = 0; i < primClass->DynamicChildren.size(); i++) - { - // Get class name - QString className = primClass->DynamicChildren[i].ClassName.c_str(); - - // Get icon - QIcon icon(QString("%1/%2.ico").arg(Constants::PATH_TO_OLD_ICONS).arg(className)); - - // Create and add action in popur menu - QAction *action = menu->addAction(icon, tr("Add %1").arg(className)); - addSignalMapper->setMapping(action, i); - connect(action, SIGNAL(triggered()), addSignalMapper, SLOT(map())); - } - } - - // What class is it ? - if (primClass && primClass->GeneratedChildren.size()) - { - menu->addSeparator(); - - // For each child, add a create method - for (size_t i = 0; i < primClass->GeneratedChildren.size(); i++) - { - // Get class name - QString childName = primClass->GeneratedChildren[i].ClassName.c_str(); - - // Create and add action in popur menu - QAction *action = menu->addAction(tr("Generate %1").arg(childName)); - generateSignalMapper->setMapping(action, i); - connect(action, SIGNAL(triggered()), generateSignalMapper, SLOT(map())); - } - } -} - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "primitives_view.h" +#include "primitives_model.h" +#include "world_editor_actions.h" +#include "world_editor_constants.h" + +#include "../core/core_constants.h" +#include "../landscape_editor/landscape_editor_constants.h" +#include "../landscape_editor/builder_zone_base.h" + +// NeL includes +#include +#include +#include +#include + +// Qt includes +#include +#include +#include +#include +#include + +namespace WorldEditor +{ + +PrimitivesView::PrimitivesView(QWidget *parent) + : QTreeView(parent), + m_undoStack(0), + m_worldEditorScene(0), + m_zoneBuilder(0), + m_primitivesTreeModel(0) +{ + setContextMenuPolicy(Qt::DefaultContextMenu); + + m_unloadAction = new QAction("Unload", this); + + m_saveAction = new QAction("Save", this); + m_saveAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); + + m_saveAsAction = new QAction("Save As...", this); + m_saveAsAction->setIcon(QIcon(Core::Constants::ICON_SAVE_AS)); + + m_loadLandAction = new QAction("Load landscape file", this); + m_loadLandAction->setIcon(QIcon(LandscapeEditor::Constants::ICON_ZONE_ITEM)); + + m_loadPrimitiveAction = new QAction("Load primitive file", this); + m_loadPrimitiveAction->setIcon(QIcon(Constants::ICON_ROOT_PRIMITIVE)); + + m_newPrimitiveAction = new QAction("New primitive", this); + + m_deleteAction = new QAction("Delete", this); + + m_selectChildrenAction = new QAction("Select children", this); + + m_helpAction = new QAction("Help", this); + m_helpAction->setEnabled(false); + + m_showAction = new QAction("Show", this); + m_showAction->setEnabled(false); + + m_hideAction = new QAction("Hide", this); + m_hideAction->setEnabled(false); + + connect(m_loadLandAction, SIGNAL(triggered()), this, SLOT(loadLandscape())); + connect(m_loadPrimitiveAction, SIGNAL(triggered()), this, SLOT(loadRootPrimitive())); + connect(m_newPrimitiveAction, SIGNAL(triggered()), this, SLOT(createRootPrimitive())); + connect(m_selectChildrenAction, SIGNAL(triggered()), this, SLOT(selectChildren())); + connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(deletePrimitives())); + connect(m_saveAction, SIGNAL(triggered()), this, SLOT(save())); + connect(m_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs())); + connect(m_unloadAction, SIGNAL(triggered()), this, SLOT(unload())); + connect(m_showAction, SIGNAL(triggered()), this, SLOT(showPrimitive())); + connect(m_hideAction, SIGNAL(triggered()), this, SLOT(hidePrimitive())); + +#ifdef Q_OS_DARWIN + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); +#endif +} + +PrimitivesView::~PrimitivesView() +{ +} + +void PrimitivesView::setUndoStack(QUndoStack *undoStack) +{ + m_undoStack = undoStack; +} + +void PrimitivesView::setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder) +{ + m_zoneBuilder = zoneBuilder; +} + +void PrimitivesView::setWorldScene(WorldEditorScene *worldEditorScene) +{ + m_worldEditorScene = worldEditorScene; +} + +void PrimitivesView::setModel(PrimitivesTreeModel *model) +{ + QTreeView::setModel(model); + m_primitivesTreeModel = model; +} + +void PrimitivesView::loadRootPrimitive() +{ + nlassert(m_undoStack); + nlassert(m_primitivesTreeModel); + + QStringList fileNames = QFileDialog::getOpenFileNames(this, + tr("Open NeL Ligo primitive file"), m_lastDir, + tr("All NeL Ligo primitive files (*.primitive)")); + + setCursor(Qt::WaitCursor); + if (!fileNames.isEmpty()) + { + if (fileNames.count() > 1) + m_undoStack->beginMacro(tr("Load primitive files")); + + Q_FOREACH(QString fileName, fileNames) + { + m_lastDir = QFileInfo(fileName).absolutePath(); + m_undoStack->push(new LoadRootPrimitiveCommand(fileName, m_worldEditorScene, m_primitivesTreeModel, this)); + } + + if (fileNames.count() > 1) + m_undoStack->endMacro(); + } + setCursor(Qt::ArrowCursor); +} + +void PrimitivesView::loadLandscape() +{ + nlassert(m_undoStack); + nlassert(m_zoneBuilder); + nlassert(m_primitivesTreeModel); + + QStringList fileNames = QFileDialog::getOpenFileNames(this, + tr("Open NeL Ligo land file"), m_lastDir, + tr("All NeL Ligo land files (*.land)")); + + setCursor(Qt::WaitCursor); + if (!fileNames.isEmpty()) + { + if (fileNames.count() > 1) + m_undoStack->beginMacro(tr("Load land files")); + + Q_FOREACH(QString fileName, fileNames) + { + m_lastDir = QFileInfo(fileName).absolutePath(); + m_undoStack->push(new LoadLandscapeCommand(fileName, m_primitivesTreeModel, m_zoneBuilder)); + } + + if (fileNames.count() > 1) + m_undoStack->endMacro(); + } + setCursor(Qt::ArrowCursor); +} + +void PrimitivesView::createRootPrimitive() +{ + nlassert(m_undoStack); + nlassert(m_primitivesTreeModel); + + m_undoStack->push(new CreateRootPrimitiveCommand("NewPrimitive", m_primitivesTreeModel)); +} + +void PrimitivesView::selectChildren() +{ + QModelIndexList indexList = selectionModel()->selectedRows(); + QModelIndex parentIndex = indexList.first(); + + selectionModel()->clearSelection(); + + QItemSelection itemSelection; + selectChildren(parentIndex, itemSelection); + selectionModel()->select(itemSelection, QItemSelectionModel::Select); +} + +void PrimitivesView::save() +{ + nlassert(m_primitivesTreeModel); + + QModelIndexList indexList = selectionModel()->selectedRows(); + QModelIndex index = indexList.first(); + + RootPrimitiveNode *node = static_cast(index.internalPointer()); + + if (node->data(Constants::PRIMITIVE_FILE_IS_CREATED).toBool()) + { + if (!NLLIGO::saveXmlPrimitiveFile(*node->primitives(), node->fileName().toStdString())) + QMessageBox::warning(this, "World Editor Qt", tr("Error writing output file: %1").arg(node->fileName())); + else + node->setData(Constants::PRIMITIVE_IS_MODIFIED, false); + } + else + saveAs(); +} + +void PrimitivesView::saveAs() +{ + nlassert(m_primitivesTreeModel); + + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save NeL Ligo primitive file"), m_lastDir, + tr("NeL Ligo primitive file (*.primitive)")); + + setCursor(Qt::WaitCursor); + if (!fileName.isEmpty()) + { + QModelIndexList indexList = selectionModel()->selectedRows(); + QModelIndex index = indexList.first(); + + RootPrimitiveNode *node = static_cast(index.internalPointer()); + + if (!NLLIGO::saveXmlPrimitiveFile(*node->primitives(), fileName.toStdString())) + QMessageBox::warning(this, "World Editor Qt", tr("Error writing output file: %1").arg(fileName)); + else + { + node->setFileName(fileName); + node->setData(Constants::PRIMITIVE_FILE_IS_CREATED, true); + node->setData(Constants::PRIMITIVE_IS_MODIFIED, false); + } + } + setCursor(Qt::ArrowCursor); +} + +void PrimitivesView::deletePrimitives() +{ + nlassert(m_undoStack); + nlassert(m_primitivesTreeModel); + + QModelIndexList indexList = selectionModel()->selectedRows(); + + QModelIndex index = indexList.first(); + + PrimitiveNode *node = static_cast(index.internalPointer()); + + if (node->primitiveClass()->Deletable) + m_undoStack->push(new DeletePrimitiveCommand(index, m_primitivesTreeModel, m_worldEditorScene, this)); + +} + +void PrimitivesView::unload() +{ + nlassert(m_undoStack); + nlassert(m_primitivesTreeModel); + + QModelIndexList indexList = selectionModel()->selectedRows(); + QModelIndex index = indexList.first(); + Node *node = static_cast(index.internalPointer()); + switch (node->type()) + { + case Node::WorldEditNodeType: + { + break; + } + case Node::LandscapeNodeType: + { + m_undoStack->push(new UnloadLandscapeCommand(index, m_primitivesTreeModel, m_zoneBuilder)); + break; + } + case Node::RootPrimitiveNodeType: + { + m_undoStack->push(new UnloadRootPrimitiveCommand(index, m_worldEditorScene, m_primitivesTreeModel, this)); + break; + } + } +} + +void PrimitivesView::showPrimitive() +{ +} + +void PrimitivesView::hidePrimitive() +{ +} + +void PrimitivesView::addNewPrimitiveByClass(int value) +{ + nlassert(m_undoStack); + nlassert(m_primitivesTreeModel); + + QModelIndexList indexList = selectionModel()->selectedRows(); + + PrimitiveNode *node = static_cast(indexList.first().internalPointer()); + + // Get class name + QString className = node->primitiveClass()->DynamicChildren[value].ClassName.c_str(); + + m_undoStack->push(new AddPrimitiveByClassCommand(className, m_primitivesTreeModel->pathFromIndex(indexList.first()), + m_worldEditorScene, m_primitivesTreeModel, this)); +} + +void PrimitivesView::generatePrimitives(int value) +{ +} + +void PrimitivesView::openItem(int value) +{ +} + +void PrimitivesView::contextMenuEvent(QContextMenuEvent *event) +{ + QWidget::contextMenuEvent(event); + QModelIndexList indexList = selectionModel()->selectedRows(); + if (indexList.size() == 0) + return; + + QMenu *popurMenu = new QMenu(this); + + if (indexList.size() == 1) + { + Node *node = static_cast(indexList.first().internalPointer()); + switch (node->type()) + { + case Node::WorldEditNodeType: + fillMenu_WorldEdit(popurMenu); + break; + case Node::RootPrimitiveNodeType: + fillMenu_RootPrimitive(popurMenu, indexList.first()); + break; + case Node::LandscapeNodeType: + fillMenu_Landscape(popurMenu); + break; + case Node::PrimitiveNodeType: + fillMenu_Primitive(popurMenu, indexList.first()); + break; + }; + } + + popurMenu->exec(event->globalPos()); + delete popurMenu; + event->accept(); +} + +void PrimitivesView::selectChildren(const QModelIndex &parent, QItemSelection &itemSelection) +{ + const int rowCount = model()->rowCount(parent); + + QItemSelection mergeItemSelection(parent.child(0, 0), parent.child(rowCount - 1, 0)); + itemSelection.merge(mergeItemSelection, QItemSelectionModel::Select); + + for (int i = 0; i < rowCount; ++i) + { + QModelIndex childIndex = parent.child(i, 0); + if (model()->rowCount(childIndex) != 0) + selectChildren(childIndex, itemSelection); + } +} + +void PrimitivesView::fillMenu_WorldEdit(QMenu *menu) +{ + //menu->addAction(m_unloadAction); + //menu->addAction(m_saveAction); + //menu->addAction(m_saveAsAction); + menu->addSeparator(); + menu->addAction(m_loadLandAction); + menu->addAction(m_loadPrimitiveAction); + menu->addAction(m_newPrimitiveAction); + menu->addSeparator(); + menu->addAction(m_helpAction); +} + +void PrimitivesView::fillMenu_Landscape(QMenu *menu) +{ + menu->addAction(m_unloadAction); + menu->addSeparator(); + menu->addAction(m_showAction); + menu->addAction(m_hideAction); +} + +void PrimitivesView::fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index) +{ + menu->addAction(m_saveAction); + menu->addAction(m_saveAsAction); + menu->addAction(m_unloadAction); + fillMenu_Primitive(menu, index); + menu->removeAction(m_deleteAction); +} + +void PrimitivesView::fillMenu_Primitive(QMenu *menu, const QModelIndex &index) +{ + menu->addAction(m_deleteAction); + menu->addAction(m_selectChildrenAction); + menu->addAction(m_helpAction); + menu->addSeparator(); + menu->addAction(m_showAction); + menu->addAction(m_hideAction); + + QSignalMapper *addSignalMapper = new QSignalMapper(menu); + QSignalMapper *generateSignalMapper = new QSignalMapper(menu); + //QSignalMapper *openSignalMapper = new QSignalMapper(menu); + connect(addSignalMapper, SIGNAL(mapped(int)), this, SLOT(addNewPrimitiveByClass(int))); + connect(generateSignalMapper, SIGNAL(mapped(int)), this, SLOT(generatePrimitives(int))); + //connect(openSignalMapper, SIGNAL(mapped(int)), this, SLOT(openItem(int))); + + PrimitiveNode *node = static_cast(index.internalPointer()); + const NLLIGO::CPrimitiveClass *primClass = node->primitiveClass(); + + // What class is it ? + if (primClass && primClass->DynamicChildren.size()) + { + menu->addSeparator(); + + // For each child, add a create method + for (size_t i = 0; i < primClass->DynamicChildren.size(); i++) + { + // Get class name + QString className = primClass->DynamicChildren[i].ClassName.c_str(); + + // Get icon + QIcon icon(QString("%1/%2.ico").arg(Constants::PATH_TO_OLD_ICONS).arg(className)); + + // Create and add action in popur menu + QAction *action = menu->addAction(icon, tr("Add %1").arg(className)); + addSignalMapper->setMapping(action, i); + connect(action, SIGNAL(triggered()), addSignalMapper, SLOT(map())); + } + } + + // What class is it ? + if (primClass && primClass->GeneratedChildren.size()) + { + menu->addSeparator(); + + // For each child, add a create method + for (size_t i = 0; i < primClass->GeneratedChildren.size(); i++) + { + // Get class name + QString childName = primClass->GeneratedChildren[i].ClassName.c_str(); + + // Create and add action in popur menu + QAction *action = menu->addAction(tr("Generate %1").arg(childName)); + generateSignalMapper->setMapping(action, i); + connect(action, SIGNAL(triggered()), generateSignalMapper, SLOT(map())); + } + } +} + } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h index 8da877658..5810b6780 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/primitives_view.h @@ -1,112 +1,112 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef PRIMITIVES_VIEW_H -#define PRIMITIVES_VIEW_H - -// Project includes -#include "primitive_item.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include -#include -#include -#include - -namespace LandscapeEditor -{ -class ZoneBuilderBase; -} - -namespace WorldEditor -{ -class PrimitivesTreeModel; -class WorldEditorScene; - -/** -@class PrimitivesView -@brief -@details -*/ -class PrimitivesView : public QTreeView -{ - Q_OBJECT - -public: - explicit PrimitivesView(QWidget *parent = 0); - ~PrimitivesView(); - - void setUndoStack(QUndoStack *undoStack); - void setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder); - void setWorldScene(WorldEditorScene *worldEditorScene); - virtual void setModel(PrimitivesTreeModel *model); - -private Q_SLOTS: - void loadLandscape(); - void loadRootPrimitive(); - void createRootPrimitive(); - void selectChildren(); - - void save(); - void saveAs(); - void deletePrimitives(); - void unload(); - void showPrimitive(); - void hidePrimitive(); - void addNewPrimitiveByClass(int value); - void generatePrimitives(int value); - void openItem(int value); - -protected: - void contextMenuEvent(QContextMenuEvent *event); - -private: - void selectChildren(const QModelIndex &parent, QItemSelection &itemSelection); - void fillMenu_WorldEdit(QMenu *menu); - void fillMenu_Landscape(QMenu *menu); - void fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index); - void fillMenu_Primitive(QMenu *menu, const QModelIndex &index); - - QString m_lastDir; - - QAction *m_unloadAction; - QAction *m_saveAction; - QAction *m_saveAsAction; - QAction *m_loadLandAction; - QAction *m_loadPrimitiveAction; - QAction *m_newPrimitiveAction; - QAction *m_deleteAction; - QAction *m_selectChildrenAction; - QAction *m_helpAction; - QAction *m_showAction; - QAction *m_hideAction; - - QUndoStack *m_undoStack; - WorldEditorScene *m_worldEditorScene; - LandscapeEditor::ZoneBuilderBase *m_zoneBuilder; - PrimitivesTreeModel *m_primitivesTreeModel; -}; - -} /* namespace WorldEditor */ - -#endif // PRIMITIVES_VIEW_H +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PRIMITIVES_VIEW_H +#define PRIMITIVES_VIEW_H + +// Project includes +#include "primitive_item.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include + +namespace LandscapeEditor +{ +class ZoneBuilderBase; +} + +namespace WorldEditor +{ +class PrimitivesTreeModel; +class WorldEditorScene; + +/** +@class PrimitivesView +@brief +@details +*/ +class PrimitivesView : public QTreeView +{ + Q_OBJECT + +public: + explicit PrimitivesView(QWidget *parent = 0); + ~PrimitivesView(); + + void setUndoStack(QUndoStack *undoStack); + void setZoneBuilder(LandscapeEditor::ZoneBuilderBase *zoneBuilder); + void setWorldScene(WorldEditorScene *worldEditorScene); + virtual void setModel(PrimitivesTreeModel *model); + +private Q_SLOTS: + void loadLandscape(); + void loadRootPrimitive(); + void createRootPrimitive(); + void selectChildren(); + + void save(); + void saveAs(); + void deletePrimitives(); + void unload(); + void showPrimitive(); + void hidePrimitive(); + void addNewPrimitiveByClass(int value); + void generatePrimitives(int value); + void openItem(int value); + +protected: + void contextMenuEvent(QContextMenuEvent *event); + +private: + void selectChildren(const QModelIndex &parent, QItemSelection &itemSelection); + void fillMenu_WorldEdit(QMenu *menu); + void fillMenu_Landscape(QMenu *menu); + void fillMenu_RootPrimitive(QMenu *menu, const QModelIndex &index); + void fillMenu_Primitive(QMenu *menu, const QModelIndex &index); + + QString m_lastDir; + + QAction *m_unloadAction; + QAction *m_saveAction; + QAction *m_saveAsAction; + QAction *m_loadLandAction; + QAction *m_loadPrimitiveAction; + QAction *m_newPrimitiveAction; + QAction *m_deleteAction; + QAction *m_selectChildrenAction; + QAction *m_helpAction; + QAction *m_showAction; + QAction *m_hideAction; + + QUndoStack *m_undoStack; + WorldEditorScene *m_worldEditorScene; + LandscapeEditor::ZoneBuilderBase *m_zoneBuilder; + PrimitivesTreeModel *m_primitivesTreeModel; +}; + +} /* namespace WorldEditor */ + +#endif // PRIMITIVES_VIEW_H diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp index 42e921106..86da1bb31 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/project_settings_dialog.cpp @@ -1,68 +1,68 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "project_settings_dialog.h" -#include "world_editor_misc.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include -#include - -// Qt includes -#include -#include -#include - -namespace WorldEditor -{ - -ProjectSettingsDialog::ProjectSettingsDialog(const QString &dataPath, QWidget *parent) - : QDialog(parent) -{ - m_ui.setupUi(this); - m_ui.pathLineEdit->setText(dataPath); - m_ui.contextComboBox->addItem("empty"); - - // Init the combo box - const std::vector &contexts = Utils::ligoConfig()->getContextString(); - for (uint i = 0; i < contexts.size(); i++) - m_ui.contextComboBox->addItem(QString(contexts[i].c_str())); - - setFixedHeight(sizeHint().height()); - connect(m_ui.selectPathButton, SIGNAL(clicked()), this, SLOT(selectPath())); -} - -ProjectSettingsDialog::~ProjectSettingsDialog() -{ -} - -QString ProjectSettingsDialog::dataPath() const -{ - return m_ui.pathLineEdit->text(); -} - -void ProjectSettingsDialog::selectPath() -{ - QString dataPath = QFileDialog::getExistingDirectory(this, tr("Select data path"), m_ui.pathLineEdit->text()); - if (!dataPath.isEmpty()) - m_ui.pathLineEdit->setText(dataPath); -} - -} /* namespace WorldEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "project_settings_dialog.h" +#include "world_editor_misc.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include +#include + +// Qt includes +#include +#include +#include + +namespace WorldEditor +{ + +ProjectSettingsDialog::ProjectSettingsDialog(const QString &dataPath, QWidget *parent) + : QDialog(parent) +{ + m_ui.setupUi(this); + m_ui.pathLineEdit->setText(dataPath); + m_ui.contextComboBox->addItem("empty"); + + // Init the combo box + const std::vector &contexts = Utils::ligoConfig()->getContextString(); + for (uint i = 0; i < contexts.size(); i++) + m_ui.contextComboBox->addItem(QString(contexts[i].c_str())); + + setFixedHeight(sizeHint().height()); + connect(m_ui.selectPathButton, SIGNAL(clicked()), this, SLOT(selectPath())); +} + +ProjectSettingsDialog::~ProjectSettingsDialog() +{ +} + +QString ProjectSettingsDialog::dataPath() const +{ + return m_ui.pathLineEdit->text(); +} + +void ProjectSettingsDialog::selectPath() +{ + QString dataPath = QFileDialog::getExistingDirectory(this, tr("Select data path"), m_ui.pathLineEdit->text()); + if (!dataPath.isEmpty()) + m_ui.pathLineEdit->setText(dataPath); +} + +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp index 0f9d91ef2..b8ca7138d 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_actions.cpp @@ -1,791 +1,791 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_actions.h" -#include "world_editor_constants.h" -#include "world_editor_misc.h" -#include "primitive_item.h" -#include "world_editor_scene.h" -#include "world_editor_scene_item.h" - -// Lanscape Editor plugin -#include "../landscape_editor/builder_zone_base.h" - -// STL includes -#include - -// NeL includes -#include -#include -#include -#include -#include -#include - -// Qt includes -#include -#include -#include - -namespace WorldEditor -{ - -QGraphicsItem *getGraphicsItem(Node *node) -{ - QGraphicsItem *result = 0; - if (node->type() == Node::PrimitiveNodeType) - { - PrimitiveNode *primitiveNode = static_cast(node); - if (primitiveNode != 0) - { - switch (primitiveNode->primitiveClass()->Type) - { - case NLLIGO::CPrimitiveClass::Point: - case NLLIGO::CPrimitiveClass::Path: - case NLLIGO::CPrimitiveClass::Zone: - { - result = qvariant_cast(primitiveNode->data(Constants::GRAPHICS_DATA_QT4_2D)); - break; - } - } - } - } - return result; -} - -void addNewGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene) -{ - PrimitiveNode *node = static_cast(primIndex.internalPointer()); - - float cellSize = Utils::ligoConfig()->CellSize; - if (node != 0) - { - NLLIGO::IPrimitive *primitive = node->primitive(); - NLLIGO::CPrimVector *vec = 0; - AbstractWorldItem *item = 0; - - // Draw arrow ? - bool showArrow = node->primitiveClass()->ShowArrow; - - switch (node->primitiveClass()->Type) - { - case NLLIGO::CPrimitiveClass::Point: - { - vec = primitive->getPrimVector(); - NLLIGO::CPrimPoint *primPoint = static_cast(primitive); - - // Have a radius ? - std::string strRadius; - qreal radius = 0; - if (primitive->getPropertyByName ("radius", strRadius)) - radius = atof(strRadius.c_str()); - qreal angle = ((2 * NLMISC::Pi - primPoint->Angle) * 180 / NLMISC::Pi); - item = scene->addWorldItemPoint(QPointF(vec->x, -vec->y + cellSize), - angle, radius, showArrow); - break; - } - case NLLIGO::CPrimitiveClass::Path: - { - QPolygonF polygon; - vec = primitive->getPrimVector(); - int sizeVec = primitive->getNumVector(); - for (int i = 0; i < sizeVec; ++i) - { - polygon << QPointF(vec->x, -vec->y + cellSize); - ++vec; - } - item = scene->addWorldItemPath(polygon, showArrow); - break; - } - case NLLIGO::CPrimitiveClass::Zone: - { - QPolygonF polygon; - vec = primitive->getPrimVector(); - int sizeVec = primitive->getNumVector(); - for (int i = 0; i < sizeVec; ++i) - { - polygon << QPointF(vec->x, cellSize - vec->y); - ++vec; - } - item = scene->addWorldItemZone(polygon); - break; - } - } - - if (item != 0) - { - // Get color from world_editor_classes.xml - NLMISC::CRGBA color = Utils::ligoConfig()->getPrimitiveColor(*primitive); - primitive->getPropertyByName ("Color", color); - item->setColor(QColor(color.R, color.G, color.B)); - - QVariant variantNode; - variantNode.setValue(node); - item->setData(Constants::WORLD_EDITOR_NODE, variantNode); - - QVariant graphicsData; - graphicsData.setValue(item); - node->setData(Constants::GRAPHICS_DATA_QT4_2D, graphicsData); - - QVariant persistenVariant; - QPersistentModelIndex *persistentIndex = new QPersistentModelIndex(primIndex); - persistenVariant.setValue(persistentIndex); - item->setData(Constants::NODE_PERISTENT_INDEX, persistenVariant); - } - } - - int count = model->rowCount(primIndex); - for (int i = 0; i < count; ++i) - { - addNewGraphicsItems(primIndex.child(i, 0), model, scene); - } -} - -void removeGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene) -{ - Node *node = static_cast(primIndex.internalPointer()); - - if (node != 0) - { - QGraphicsItem *item = getGraphicsItem(node); - if (item != 0) - { - delete qvariant_cast(item->data(Constants::NODE_PERISTENT_INDEX)); - scene->removeWorldItem(item); - } - } - - int count = model->rowCount(primIndex); - for (int i = 0; i < count; ++i) - { - removeGraphicsItems(primIndex.child(i, 0), model, scene); - } -} - -QList polygonsFromItems(const QList &items) -{ - QList result; - Q_FOREACH(QGraphicsItem *item, items) - { - AbstractWorldItem *worldItem = qgraphicsitem_cast(item); - result.push_back(worldItem->polygon()); - } - return result; -} - -CreateWorldCommand::CreateWorldCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent) - : QUndoCommand(parent), - m_fileName(fileName), - m_model(model) -{ - setText(QObject::tr("Create new world")); -} - -CreateWorldCommand::~CreateWorldCommand() -{ -} - -void CreateWorldCommand::undo() -{ - m_model->deleteWorldEditNode(); -} - -void CreateWorldCommand::redo() -{ - m_model->createWorldEditNode(m_fileName); -} - -LoadLandscapeCommand::LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model, - LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) - : QUndoCommand(parent), - m_id(-1), - m_fileName(fileName), - m_model(model), - m_zoneBuilder(zoneBuilder) -{ - setText(QObject::tr("Load land file")); -} - -LoadLandscapeCommand::~LoadLandscapeCommand() -{ -} - -void LoadLandscapeCommand::undo() -{ - m_zoneBuilder->deleteZoneRegion(m_id); - m_model->deleteNode(landIndex); -} - -void LoadLandscapeCommand::redo() -{ - if (m_id == -1) - m_id = m_zoneBuilder->loadZoneRegion(m_fileName); - else - m_zoneBuilder->loadZoneRegion(m_fileName, m_id); - - landIndex = m_model->createLandscapeNode(m_fileName, m_id); -} - - -UnloadLandscapeCommand::UnloadLandscapeCommand(const QModelIndex &index, PrimitivesTreeModel *model, - LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) - : QUndoCommand(parent), - m_model(model), - m_zoneBuilder(zoneBuilder) -{ - setText(QObject::tr("Unload land file")); - m_path = m_model->pathFromIndex(index); -} - -UnloadLandscapeCommand::~UnloadLandscapeCommand() -{ -} - -void UnloadLandscapeCommand::undo() -{ - m_zoneBuilder->loadZoneRegion(m_fileName, m_id); - - m_model->createLandscapeNode(m_fileName, m_id, m_path.back().first); -} - -void UnloadLandscapeCommand::redo() -{ - QModelIndex index = m_model->pathToIndex(m_path); - LandscapeNode *node = static_cast(index.internalPointer()); - - m_id = node->id(); - m_fileName = node->fileName(); - - m_zoneBuilder->deleteZoneRegion(m_id); - m_model->deleteNode(m_path); -} - -CreateRootPrimitiveCommand::CreateRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent) - : QUndoCommand(parent), - m_fileName(fileName), - m_model(model) -{ - setText(QObject::tr("Create new primitive")); -} - -CreateRootPrimitiveCommand::~CreateRootPrimitiveCommand() -{ -} - -void CreateRootPrimitiveCommand::undo() -{ - QModelIndex index = m_model->pathToIndex(m_rootPrimIndex); - - RootPrimitiveNode *node = static_cast(index.internalPointer()); - - delete node->primitives(); - - m_model->deleteNode(m_rootPrimIndex); -} - -void CreateRootPrimitiveCommand::redo() -{ - NLLIGO::CPrimitives *newRootPrim = new NLLIGO::CPrimitives(); - m_rootPrimIndex = m_model->createRootPrimitiveNode("", newRootPrim); -} - - -LoadRootPrimitiveCommand::LoadRootPrimitiveCommand(const QString &fileName, WorldEditorScene *scene, - PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) - : QUndoCommand(parent), - m_fileName(fileName), - m_scene(scene), - m_model(model), - m_view(view) -{ - setText(QObject::tr("Load primitive file")); -} - -LoadRootPrimitiveCommand::~LoadRootPrimitiveCommand() -{ -} - -void LoadRootPrimitiveCommand::undo() -{ - // Disable edit points mode - m_scene->setEnabledEditPoints(false); - - m_view->selectionModel()->clearSelection(); - - QModelIndex index = m_model->pathToIndex(m_rootPrimIndex); - - removeGraphicsItems(index, m_model, m_scene); - - RootPrimitiveNode *node = static_cast(index.internalPointer()); - - delete node->primitives(); - - m_model->deleteNode(m_rootPrimIndex); -} - -void LoadRootPrimitiveCommand::redo() -{ - m_scene->setEnabledEditPoints(false); - - NLLIGO::CPrimitives *primitives = new NLLIGO::CPrimitives(); - - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = primitives; - - NLLIGO::loadXmlPrimitiveFile(*primitives, m_fileName.toStdString(), *Utils::ligoConfig()); - - // unset the context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; - - - // Initialize default values - Utils::recursiveUpdateDefaultValues(primitives->RootNode); - - // Check property types - if (Utils::recursiveUpdateDefaultValues(primitives->RootNode)) - { - nlwarning("In file (%s) : Some primitives have been modified to initialise their default values\nor to change their properties type.", m_fileName.toStdString().c_str()); - } - - m_rootPrimIndex = m_model->createRootPrimitiveNode(m_fileName, primitives); - - addNewGraphicsItems(m_model->pathToIndex(m_rootPrimIndex), m_model, m_scene); -} - - -UnloadRootPrimitiveCommand::UnloadRootPrimitiveCommand(const QModelIndex &index, WorldEditorScene *scene, - PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) - : QUndoCommand(parent), - m_scene(scene), - m_model(model), - m_view(view) -{ - setText(QObject::tr("Unload primitive file")); - m_path = m_model->pathFromIndex(index); -} - -UnloadRootPrimitiveCommand::~UnloadRootPrimitiveCommand() -{ -} - -void UnloadRootPrimitiveCommand::undo() -{ - // Disable edit points mode - m_scene->setEnabledEditPoints(false); - - m_path = m_model->createRootPrimitiveNode(m_fileName, m_primitives, m_path.back().first); - - addNewGraphicsItems(m_model->pathToIndex(m_path), m_model, m_scene); -} - -void UnloadRootPrimitiveCommand::redo() -{ - m_scene->setEnabledEditPoints(false); - - m_view->selectionModel()->clearSelection(); - QModelIndex index = m_model->pathToIndex(m_path); - RootPrimitiveNode *node = static_cast(index.internalPointer()); - m_fileName = node->fileName(); - m_primitives = node->primitives(); - - removeGraphicsItems(index, m_model, m_scene); - - m_model->deleteNode(m_path); -} - -AddPrimitiveByClassCommand::AddPrimitiveByClassCommand(const QString &className, const Path &parentIndex, - WorldEditorScene *scene, PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) - : QUndoCommand(parent), - m_className(className), - m_parentIndex(parentIndex), - m_scene(scene), - m_model(model), - m_view(view) -{ - setText(QObject::tr("Add %1").arg(m_className)); - - QGraphicsView *graphicsView = m_scene->views().first(); - - // TODO: returns incorrect position when zoom in - QRectF visibleArea = graphicsView->mapToScene(view->rect()).boundingRect(); - m_delta = visibleArea.height() / 10.0; - m_initPos = visibleArea.center(); -} - -AddPrimitiveByClassCommand::~AddPrimitiveByClassCommand() -{ -} - -void AddPrimitiveByClassCommand::undo() -{ - m_scene->setEnabledEditPoints(false); - - m_view->selectionModel()->clearSelection(); - - QModelIndex index = m_model->pathToIndex(m_newPrimIndex); - PrimitiveNode *node = static_cast(index.internalPointer()); - - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = node->rootPrimitiveNode()->primitives(); - - removeGraphicsItems(index, m_model, m_scene); - - Utils::deletePrimitive(node->primitive()); - - // unset the context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; - - m_model->deleteNode(m_newPrimIndex); -} - -void AddPrimitiveByClassCommand::redo() -{ - m_scene->setEnabledEditPoints(false); - - QModelIndex parentIndex = m_model->pathToIndex(m_parentIndex); - PrimitiveNode *parentNode = static_cast(parentIndex.internalPointer()); - const NLLIGO::CPrimitiveClass *primClass = parentNode->primitiveClass(); - - int id = 0; - while (primClass->DynamicChildren[id].ClassName != m_className.toStdString()) - ++id; - - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = parentNode->rootPrimitiveNode()->primitives(); - - QString namePrimititve = QString("%1_%2").arg(m_className).arg(parentNode->childCount()); - NLLIGO::IPrimitive *newPrimitive = Utils::createPrimitive(m_className.toStdString().c_str(), namePrimititve.toStdString().c_str(), - NLMISC::CVector(m_initPos.x(), -m_initPos.y(), 0.0), m_delta, primClass->DynamicChildren[id].Parameters, parentNode->primitive()); - - // unset the context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; - - m_newPrimIndex = m_model->createPrimitiveNode(newPrimitive, m_parentIndex); - - addNewGraphicsItems(m_model->pathToIndex(m_newPrimIndex), m_model, m_scene); -} - -DeletePrimitiveCommand::DeletePrimitiveCommand(const QModelIndex &index, PrimitivesTreeModel *model, - WorldEditorScene *scene, QTreeView *view, QUndoCommand *parent) - : QUndoCommand(parent), - m_scene(scene), - m_model(model), - m_view(view) -{ - setText(QObject::tr("Delete primitive")); - - // Save path to primitive - m_path = m_model->pathFromIndex(index); - m_parentPath = m_model->pathFromIndex(index.parent()); - - PrimitiveNode *node = static_cast(index.internalPointer()); - - NLLIGO::IPrimitive *primitive = node->primitive(); - - // Backup primitive - m_oldPrimitive = primitive->copy(); - - // Backup position primitive - primitive->getParent()->getChildId(m_posPrimitive, primitive); -} - -DeletePrimitiveCommand::~DeletePrimitiveCommand() -{ - delete m_oldPrimitive; -} - -void DeletePrimitiveCommand::undo() -{ - m_scene->setEnabledEditPoints(false); - m_view->selectionModel()->clearSelection(); - - QModelIndex parentIndex = m_model->pathToIndex(m_parentPath); - PrimitiveNode *parentNode = static_cast(parentIndex.internalPointer()); - - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = parentNode->rootPrimitiveNode()->primitives(); - - NLLIGO::IPrimitive *newPrimitive = m_oldPrimitive->copy(); - if (!parentNode->primitive()->insertChild(newPrimitive, m_posPrimitive)) - nlerror("Primitive can't insert, m_posPrimitive is not a valid."); - - // Insert primitive node in tree model - Path newPath = m_model->createPrimitiveNode(newPrimitive, m_parentPath, m_path.back().first); - - // Scan graphics model - addNewGraphicsItems(m_model->pathToIndex(newPath), m_model, m_scene); - - // unset the context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; -} - -void DeletePrimitiveCommand::redo() -{ - m_scene->setEnabledEditPoints(false); - m_view->selectionModel()->clearSelection(); - - QModelIndex index = m_model->pathToIndex(m_path); - PrimitiveNode *node = static_cast(index.internalPointer()); - NLLIGO::IPrimitive *primitive = node->primitive(); - - // Removes all graphics items - removeGraphicsItems(index, m_model, m_scene); - - // set the primitive context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = node->rootPrimitiveNode()->primitives(); - - // Delete primitive - Utils::deletePrimitive(primitive); - - // unset the context - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; - - // Remove primitive from tree model - m_model->deleteNode(m_path); -} - -AbstractWorldItemCommand::AbstractWorldItemCommand(const QList &items, - WorldEditorScene *scene, - PrimitivesTreeModel *model, - QUndoCommand *parent) - : QUndoCommand(parent), - m_listPaths(graphicsItemsToPaths(items, model)), - m_model(model), - m_scene(scene), - m_firstRun(true) -{ -} - -AbstractWorldItemCommand::~AbstractWorldItemCommand() -{ -} - -void AbstractWorldItemCommand::undo() -{ - bool pointsMode = m_scene->isEnabledEditPoints(); - m_scene->setEnabledEditPoints(false); - for (int i = 0; i < m_listPaths.count(); ++i) - { - Node *node = m_model->pathToNode(m_listPaths.at(i)); - AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); - undoChangeItem(i, item); - updatePrimitiveData(item); - } - m_scene->setEnabledEditPoints(pointsMode); -} - -void AbstractWorldItemCommand::redo() -{ - if (!m_firstRun) - { - bool pointsMode = m_scene->isEnabledEditPoints(); - m_scene->setEnabledEditPoints(false); - for (int i = 0; i < m_listPaths.count(); ++i) - { - Node *node = m_model->pathToNode(m_listPaths.at(i)); - AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); - redoChangeItem(i, item); - updatePrimitiveData(item); - } - m_scene->setEnabledEditPoints(pointsMode); - } - else - { - for (int i = 0; i < m_listPaths.count(); ++i) - { - Node *node = m_model->pathToNode(m_listPaths.at(i)); - AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); - updatePrimitiveData(item); - } - } - - m_firstRun = false; -} - -void AbstractWorldItemCommand::updatePrimitiveData(AbstractWorldItem *item) -{ - float cellSize = Utils::ligoConfig()->CellSize; - Node *node = qvariant_cast(item->data(Constants::WORLD_EDITOR_NODE)); - PrimitiveNode *primitiveNode = static_cast(node); - if (primitiveNode != 0) - { - NLLIGO::IPrimitive *primitive = primitiveNode->primitive(); - - std::vector vPoints; - QPolygonF polygon = item->polygon(); - polygon.translate(item->pos()); - - for (int i = 0; i < polygon.size(); ++i) - { - NLMISC::CVector vec(polygon.at(i).x(), cellSize - polygon.at(i).y(), 0.0); - vPoints.push_back(NLLIGO::CPrimVector(vec)); - } - - switch (primitiveNode->primitiveClass()->Type) - { - case NLLIGO::CPrimitiveClass::Point: - { - qreal angle = static_cast(item)->angle(); - angle = 2 * NLMISC::Pi - (angle * NLMISC::Pi / 180.0); - NLLIGO::CPrimPoint *point = static_cast(primitive); - point->Point = vPoints.front(); - point->Angle = angle; - break; - } - case NLLIGO::CPrimitiveClass::Path: - { - NLLIGO::CPrimPath *path = static_cast(primitive); - path->VPoints = vPoints; - break; - } - case NLLIGO::CPrimitiveClass::Zone: - { - NLLIGO::CPrimZone *zone = static_cast(primitive); - zone->VPoints = vPoints; - break; - } - } - } -} - -QList AbstractWorldItemCommand::graphicsItemsToPaths(const QList &items, PrimitivesTreeModel *model) -{ - QList result; - Q_FOREACH(QGraphicsItem *item, items) - { - Node *node = qvariant_cast(item->data(Constants::WORLD_EDITOR_NODE)); - result.push_back(model->pathFromNode(node)); - } - return result; -} - -MoveWorldItemsCommand::MoveWorldItemsCommand(const QList &items, const QPointF &offset, - WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) - : AbstractWorldItemCommand(items, scene, model, parent), - m_offset(offset) -{ - setText(QObject::tr("Move item(s)")); -} - -MoveWorldItemsCommand::~MoveWorldItemsCommand() -{ -} - -void MoveWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) -{ - item->moveBy(-m_offset.x(), -m_offset.y()); -} - -void MoveWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) -{ - item->moveBy(m_offset.x(), m_offset.y()); -} - -RotateWorldItemsCommand::RotateWorldItemsCommand(const QList &items, const qreal angle, - const QPointF &pivot, WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) - : AbstractWorldItemCommand(items, scene, model, parent), - m_angle(angle), - m_pivot(pivot) -{ - setText(QObject::tr("Rotate item(s)")); -} - -RotateWorldItemsCommand::~RotateWorldItemsCommand() -{ -} - -void RotateWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) -{ - item->rotateOn(m_pivot, -m_angle); -} - -void RotateWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) -{ - item->rotateOn(m_pivot, m_angle); -} - -ScaleWorldItemsCommand::ScaleWorldItemsCommand(const QList &items, const QPointF &factor, - const QPointF &pivot, WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) - : AbstractWorldItemCommand(items, scene, model, parent), - m_factor(factor), - m_pivot(pivot) -{ - setText(QObject::tr("Scale item(s)")); -} - -ScaleWorldItemsCommand::~ScaleWorldItemsCommand() -{ -} - -void ScaleWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) -{ - QPointF m_invertFactor(1 / m_factor.x(), 1 / m_factor.y()); - item->scaleOn(m_pivot, m_invertFactor); -} - -void ScaleWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) -{ - item->scaleOn(m_pivot, m_factor); -} - -TurnWorldItemsCommand::TurnWorldItemsCommand(const QList &items, const qreal angle, - WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) - : AbstractWorldItemCommand(items, scene, model, parent), - m_angle(angle) -{ - setText(QObject::tr("Turn item(s)")); -} - -TurnWorldItemsCommand::~TurnWorldItemsCommand() -{ -} - -void TurnWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) -{ - item->turnOn(-m_angle); -} - -void TurnWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) -{ - item->turnOn(m_angle); -} - -ShapeWorldItemsCommand::ShapeWorldItemsCommand(const QList &items, const QList &polygons, - WorldEditorScene *scene, PrimitivesTreeModel *model, - QUndoCommand *parent) - : AbstractWorldItemCommand(items, scene, model, parent), - m_redoPolygons(polygons), - m_undoPolygons(polygonsFromItems(items)) -{ - setText(QObject::tr("Change shape")); -} - -ShapeWorldItemsCommand::~ShapeWorldItemsCommand() -{ -} - -void ShapeWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) -{ - item->setPolygon(m_redoPolygons.at(i)); -} - -void ShapeWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) -{ - item->setPolygon(m_undoPolygons.at(i)); -} - -} /* namespace WorldEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_actions.h" +#include "world_editor_constants.h" +#include "world_editor_misc.h" +#include "primitive_item.h" +#include "world_editor_scene.h" +#include "world_editor_scene_item.h" + +// Lanscape Editor plugin +#include "../landscape_editor/builder_zone_base.h" + +// STL includes +#include + +// NeL includes +#include +#include +#include +#include +#include +#include + +// Qt includes +#include +#include +#include + +namespace WorldEditor +{ + +QGraphicsItem *getGraphicsItem(Node *node) +{ + QGraphicsItem *result = 0; + if (node->type() == Node::PrimitiveNodeType) + { + PrimitiveNode *primitiveNode = static_cast(node); + if (primitiveNode != 0) + { + switch (primitiveNode->primitiveClass()->Type) + { + case NLLIGO::CPrimitiveClass::Point: + case NLLIGO::CPrimitiveClass::Path: + case NLLIGO::CPrimitiveClass::Zone: + { + result = qvariant_cast(primitiveNode->data(Constants::GRAPHICS_DATA_QT4_2D)); + break; + } + } + } + } + return result; +} + +void addNewGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene) +{ + PrimitiveNode *node = static_cast(primIndex.internalPointer()); + + float cellSize = Utils::ligoConfig()->CellSize; + if (node != 0) + { + NLLIGO::IPrimitive *primitive = node->primitive(); + NLLIGO::CPrimVector *vec = 0; + AbstractWorldItem *item = 0; + + // Draw arrow ? + bool showArrow = node->primitiveClass()->ShowArrow; + + switch (node->primitiveClass()->Type) + { + case NLLIGO::CPrimitiveClass::Point: + { + vec = primitive->getPrimVector(); + NLLIGO::CPrimPoint *primPoint = static_cast(primitive); + + // Have a radius ? + std::string strRadius; + qreal radius = 0; + if (primitive->getPropertyByName ("radius", strRadius)) + radius = atof(strRadius.c_str()); + qreal angle = ((2 * NLMISC::Pi - primPoint->Angle) * 180 / NLMISC::Pi); + item = scene->addWorldItemPoint(QPointF(vec->x, -vec->y + cellSize), + angle, radius, showArrow); + break; + } + case NLLIGO::CPrimitiveClass::Path: + { + QPolygonF polygon; + vec = primitive->getPrimVector(); + int sizeVec = primitive->getNumVector(); + for (int i = 0; i < sizeVec; ++i) + { + polygon << QPointF(vec->x, -vec->y + cellSize); + ++vec; + } + item = scene->addWorldItemPath(polygon, showArrow); + break; + } + case NLLIGO::CPrimitiveClass::Zone: + { + QPolygonF polygon; + vec = primitive->getPrimVector(); + int sizeVec = primitive->getNumVector(); + for (int i = 0; i < sizeVec; ++i) + { + polygon << QPointF(vec->x, cellSize - vec->y); + ++vec; + } + item = scene->addWorldItemZone(polygon); + break; + } + } + + if (item != 0) + { + // Get color from world_editor_classes.xml + NLMISC::CRGBA color = Utils::ligoConfig()->getPrimitiveColor(*primitive); + primitive->getPropertyByName ("Color", color); + item->setColor(QColor(color.R, color.G, color.B)); + + QVariant variantNode; + variantNode.setValue(node); + item->setData(Constants::WORLD_EDITOR_NODE, variantNode); + + QVariant graphicsData; + graphicsData.setValue(item); + node->setData(Constants::GRAPHICS_DATA_QT4_2D, graphicsData); + + QVariant persistenVariant; + QPersistentModelIndex *persistentIndex = new QPersistentModelIndex(primIndex); + persistenVariant.setValue(persistentIndex); + item->setData(Constants::NODE_PERISTENT_INDEX, persistenVariant); + } + } + + int count = model->rowCount(primIndex); + for (int i = 0; i < count; ++i) + { + addNewGraphicsItems(primIndex.child(i, 0), model, scene); + } +} + +void removeGraphicsItems(const QModelIndex &primIndex, PrimitivesTreeModel *model, WorldEditorScene *scene) +{ + Node *node = static_cast(primIndex.internalPointer()); + + if (node != 0) + { + QGraphicsItem *item = getGraphicsItem(node); + if (item != 0) + { + delete qvariant_cast(item->data(Constants::NODE_PERISTENT_INDEX)); + scene->removeWorldItem(item); + } + } + + int count = model->rowCount(primIndex); + for (int i = 0; i < count; ++i) + { + removeGraphicsItems(primIndex.child(i, 0), model, scene); + } +} + +QList polygonsFromItems(const QList &items) +{ + QList result; + Q_FOREACH(QGraphicsItem *item, items) + { + AbstractWorldItem *worldItem = qgraphicsitem_cast(item); + result.push_back(worldItem->polygon()); + } + return result; +} + +CreateWorldCommand::CreateWorldCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent) + : QUndoCommand(parent), + m_fileName(fileName), + m_model(model) +{ + setText(QObject::tr("Create new world")); +} + +CreateWorldCommand::~CreateWorldCommand() +{ +} + +void CreateWorldCommand::undo() +{ + m_model->deleteWorldEditNode(); +} + +void CreateWorldCommand::redo() +{ + m_model->createWorldEditNode(m_fileName); +} + +LoadLandscapeCommand::LoadLandscapeCommand(const QString &fileName, PrimitivesTreeModel *model, + LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) + : QUndoCommand(parent), + m_id(-1), + m_fileName(fileName), + m_model(model), + m_zoneBuilder(zoneBuilder) +{ + setText(QObject::tr("Load land file")); +} + +LoadLandscapeCommand::~LoadLandscapeCommand() +{ +} + +void LoadLandscapeCommand::undo() +{ + m_zoneBuilder->deleteZoneRegion(m_id); + m_model->deleteNode(landIndex); +} + +void LoadLandscapeCommand::redo() +{ + if (m_id == -1) + m_id = m_zoneBuilder->loadZoneRegion(m_fileName); + else + m_zoneBuilder->loadZoneRegion(m_fileName, m_id); + + landIndex = m_model->createLandscapeNode(m_fileName, m_id); +} + + +UnloadLandscapeCommand::UnloadLandscapeCommand(const QModelIndex &index, PrimitivesTreeModel *model, + LandscapeEditor::ZoneBuilderBase *zoneBuilder, QUndoCommand *parent) + : QUndoCommand(parent), + m_model(model), + m_zoneBuilder(zoneBuilder) +{ + setText(QObject::tr("Unload land file")); + m_path = m_model->pathFromIndex(index); +} + +UnloadLandscapeCommand::~UnloadLandscapeCommand() +{ +} + +void UnloadLandscapeCommand::undo() +{ + m_zoneBuilder->loadZoneRegion(m_fileName, m_id); + + m_model->createLandscapeNode(m_fileName, m_id, m_path.back().first); +} + +void UnloadLandscapeCommand::redo() +{ + QModelIndex index = m_model->pathToIndex(m_path); + LandscapeNode *node = static_cast(index.internalPointer()); + + m_id = node->id(); + m_fileName = node->fileName(); + + m_zoneBuilder->deleteZoneRegion(m_id); + m_model->deleteNode(m_path); +} + +CreateRootPrimitiveCommand::CreateRootPrimitiveCommand(const QString &fileName, PrimitivesTreeModel *model, QUndoCommand *parent) + : QUndoCommand(parent), + m_fileName(fileName), + m_model(model) +{ + setText(QObject::tr("Create new primitive")); +} + +CreateRootPrimitiveCommand::~CreateRootPrimitiveCommand() +{ +} + +void CreateRootPrimitiveCommand::undo() +{ + QModelIndex index = m_model->pathToIndex(m_rootPrimIndex); + + RootPrimitiveNode *node = static_cast(index.internalPointer()); + + delete node->primitives(); + + m_model->deleteNode(m_rootPrimIndex); +} + +void CreateRootPrimitiveCommand::redo() +{ + NLLIGO::CPrimitives *newRootPrim = new NLLIGO::CPrimitives(); + m_rootPrimIndex = m_model->createRootPrimitiveNode("", newRootPrim); +} + + +LoadRootPrimitiveCommand::LoadRootPrimitiveCommand(const QString &fileName, WorldEditorScene *scene, + PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) + : QUndoCommand(parent), + m_fileName(fileName), + m_scene(scene), + m_model(model), + m_view(view) +{ + setText(QObject::tr("Load primitive file")); +} + +LoadRootPrimitiveCommand::~LoadRootPrimitiveCommand() +{ +} + +void LoadRootPrimitiveCommand::undo() +{ + // Disable edit points mode + m_scene->setEnabledEditPoints(false); + + m_view->selectionModel()->clearSelection(); + + QModelIndex index = m_model->pathToIndex(m_rootPrimIndex); + + removeGraphicsItems(index, m_model, m_scene); + + RootPrimitiveNode *node = static_cast(index.internalPointer()); + + delete node->primitives(); + + m_model->deleteNode(m_rootPrimIndex); +} + +void LoadRootPrimitiveCommand::redo() +{ + m_scene->setEnabledEditPoints(false); + + NLLIGO::CPrimitives *primitives = new NLLIGO::CPrimitives(); + + // set the primitive context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = primitives; + + NLLIGO::loadXmlPrimitiveFile(*primitives, m_fileName.toStdString(), *Utils::ligoConfig()); + + // unset the context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; + + + // Initialize default values + Utils::recursiveUpdateDefaultValues(primitives->RootNode); + + // Check property types + if (Utils::recursiveUpdateDefaultValues(primitives->RootNode)) + { + nlwarning("In file (%s) : Some primitives have been modified to initialise their default values\nor to change their properties type.", m_fileName.toStdString().c_str()); + } + + m_rootPrimIndex = m_model->createRootPrimitiveNode(m_fileName, primitives); + + addNewGraphicsItems(m_model->pathToIndex(m_rootPrimIndex), m_model, m_scene); +} + + +UnloadRootPrimitiveCommand::UnloadRootPrimitiveCommand(const QModelIndex &index, WorldEditorScene *scene, + PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) + : QUndoCommand(parent), + m_scene(scene), + m_model(model), + m_view(view) +{ + setText(QObject::tr("Unload primitive file")); + m_path = m_model->pathFromIndex(index); +} + +UnloadRootPrimitiveCommand::~UnloadRootPrimitiveCommand() +{ +} + +void UnloadRootPrimitiveCommand::undo() +{ + // Disable edit points mode + m_scene->setEnabledEditPoints(false); + + m_path = m_model->createRootPrimitiveNode(m_fileName, m_primitives, m_path.back().first); + + addNewGraphicsItems(m_model->pathToIndex(m_path), m_model, m_scene); +} + +void UnloadRootPrimitiveCommand::redo() +{ + m_scene->setEnabledEditPoints(false); + + m_view->selectionModel()->clearSelection(); + QModelIndex index = m_model->pathToIndex(m_path); + RootPrimitiveNode *node = static_cast(index.internalPointer()); + m_fileName = node->fileName(); + m_primitives = node->primitives(); + + removeGraphicsItems(index, m_model, m_scene); + + m_model->deleteNode(m_path); +} + +AddPrimitiveByClassCommand::AddPrimitiveByClassCommand(const QString &className, const Path &parentIndex, + WorldEditorScene *scene, PrimitivesTreeModel *model, QTreeView *view, QUndoCommand *parent) + : QUndoCommand(parent), + m_className(className), + m_parentIndex(parentIndex), + m_scene(scene), + m_model(model), + m_view(view) +{ + setText(QObject::tr("Add %1").arg(m_className)); + + QGraphicsView *graphicsView = m_scene->views().first(); + + // TODO: returns incorrect position when zoom in + QRectF visibleArea = graphicsView->mapToScene(view->rect()).boundingRect(); + m_delta = visibleArea.height() / 10.0; + m_initPos = visibleArea.center(); +} + +AddPrimitiveByClassCommand::~AddPrimitiveByClassCommand() +{ +} + +void AddPrimitiveByClassCommand::undo() +{ + m_scene->setEnabledEditPoints(false); + + m_view->selectionModel()->clearSelection(); + + QModelIndex index = m_model->pathToIndex(m_newPrimIndex); + PrimitiveNode *node = static_cast(index.internalPointer()); + + // set the primitive context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = node->rootPrimitiveNode()->primitives(); + + removeGraphicsItems(index, m_model, m_scene); + + Utils::deletePrimitive(node->primitive()); + + // unset the context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; + + m_model->deleteNode(m_newPrimIndex); +} + +void AddPrimitiveByClassCommand::redo() +{ + m_scene->setEnabledEditPoints(false); + + QModelIndex parentIndex = m_model->pathToIndex(m_parentIndex); + PrimitiveNode *parentNode = static_cast(parentIndex.internalPointer()); + const NLLIGO::CPrimitiveClass *primClass = parentNode->primitiveClass(); + + int id = 0; + while (primClass->DynamicChildren[id].ClassName != m_className.toStdString()) + ++id; + + // set the primitive context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = parentNode->rootPrimitiveNode()->primitives(); + + QString namePrimititve = QString("%1_%2").arg(m_className).arg(parentNode->childCount()); + NLLIGO::IPrimitive *newPrimitive = Utils::createPrimitive(m_className.toStdString().c_str(), namePrimititve.toStdString().c_str(), + NLMISC::CVector(m_initPos.x(), -m_initPos.y(), 0.0), m_delta, primClass->DynamicChildren[id].Parameters, parentNode->primitive()); + + // unset the context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; + + m_newPrimIndex = m_model->createPrimitiveNode(newPrimitive, m_parentIndex); + + addNewGraphicsItems(m_model->pathToIndex(m_newPrimIndex), m_model, m_scene); +} + +DeletePrimitiveCommand::DeletePrimitiveCommand(const QModelIndex &index, PrimitivesTreeModel *model, + WorldEditorScene *scene, QTreeView *view, QUndoCommand *parent) + : QUndoCommand(parent), + m_scene(scene), + m_model(model), + m_view(view) +{ + setText(QObject::tr("Delete primitive")); + + // Save path to primitive + m_path = m_model->pathFromIndex(index); + m_parentPath = m_model->pathFromIndex(index.parent()); + + PrimitiveNode *node = static_cast(index.internalPointer()); + + NLLIGO::IPrimitive *primitive = node->primitive(); + + // Backup primitive + m_oldPrimitive = primitive->copy(); + + // Backup position primitive + primitive->getParent()->getChildId(m_posPrimitive, primitive); +} + +DeletePrimitiveCommand::~DeletePrimitiveCommand() +{ + delete m_oldPrimitive; +} + +void DeletePrimitiveCommand::undo() +{ + m_scene->setEnabledEditPoints(false); + m_view->selectionModel()->clearSelection(); + + QModelIndex parentIndex = m_model->pathToIndex(m_parentPath); + PrimitiveNode *parentNode = static_cast(parentIndex.internalPointer()); + + // set the primitive context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = parentNode->rootPrimitiveNode()->primitives(); + + NLLIGO::IPrimitive *newPrimitive = m_oldPrimitive->copy(); + if (!parentNode->primitive()->insertChild(newPrimitive, m_posPrimitive)) + nlerror("Primitive can't insert, m_posPrimitive is not a valid."); + + // Insert primitive node in tree model + Path newPath = m_model->createPrimitiveNode(newPrimitive, m_parentPath, m_path.back().first); + + // Scan graphics model + addNewGraphicsItems(m_model->pathToIndex(newPath), m_model, m_scene); + + // unset the context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; +} + +void DeletePrimitiveCommand::redo() +{ + m_scene->setEnabledEditPoints(false); + m_view->selectionModel()->clearSelection(); + + QModelIndex index = m_model->pathToIndex(m_path); + PrimitiveNode *node = static_cast(index.internalPointer()); + NLLIGO::IPrimitive *primitive = node->primitive(); + + // Removes all graphics items + removeGraphicsItems(index, m_model, m_scene); + + // set the primitive context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = node->rootPrimitiveNode()->primitives(); + + // Delete primitive + Utils::deletePrimitive(primitive); + + // unset the context + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; + + // Remove primitive from tree model + m_model->deleteNode(m_path); +} + +AbstractWorldItemCommand::AbstractWorldItemCommand(const QList &items, + WorldEditorScene *scene, + PrimitivesTreeModel *model, + QUndoCommand *parent) + : QUndoCommand(parent), + m_listPaths(graphicsItemsToPaths(items, model)), + m_model(model), + m_scene(scene), + m_firstRun(true) +{ +} + +AbstractWorldItemCommand::~AbstractWorldItemCommand() +{ +} + +void AbstractWorldItemCommand::undo() +{ + bool pointsMode = m_scene->isEnabledEditPoints(); + m_scene->setEnabledEditPoints(false); + for (int i = 0; i < m_listPaths.count(); ++i) + { + Node *node = m_model->pathToNode(m_listPaths.at(i)); + AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); + undoChangeItem(i, item); + updatePrimitiveData(item); + } + m_scene->setEnabledEditPoints(pointsMode); +} + +void AbstractWorldItemCommand::redo() +{ + if (!m_firstRun) + { + bool pointsMode = m_scene->isEnabledEditPoints(); + m_scene->setEnabledEditPoints(false); + for (int i = 0; i < m_listPaths.count(); ++i) + { + Node *node = m_model->pathToNode(m_listPaths.at(i)); + AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); + redoChangeItem(i, item); + updatePrimitiveData(item); + } + m_scene->setEnabledEditPoints(pointsMode); + } + else + { + for (int i = 0; i < m_listPaths.count(); ++i) + { + Node *node = m_model->pathToNode(m_listPaths.at(i)); + AbstractWorldItem *item = qvariant_cast(node->data(Constants::GRAPHICS_DATA_QT4_2D)); + updatePrimitiveData(item); + } + } + + m_firstRun = false; +} + +void AbstractWorldItemCommand::updatePrimitiveData(AbstractWorldItem *item) +{ + float cellSize = Utils::ligoConfig()->CellSize; + Node *node = qvariant_cast(item->data(Constants::WORLD_EDITOR_NODE)); + PrimitiveNode *primitiveNode = static_cast(node); + if (primitiveNode != 0) + { + NLLIGO::IPrimitive *primitive = primitiveNode->primitive(); + + std::vector vPoints; + QPolygonF polygon = item->polygon(); + polygon.translate(item->pos()); + + for (int i = 0; i < polygon.size(); ++i) + { + NLMISC::CVector vec(polygon.at(i).x(), cellSize - polygon.at(i).y(), 0.0); + vPoints.push_back(NLLIGO::CPrimVector(vec)); + } + + switch (primitiveNode->primitiveClass()->Type) + { + case NLLIGO::CPrimitiveClass::Point: + { + qreal angle = static_cast(item)->angle(); + angle = 2 * NLMISC::Pi - (angle * NLMISC::Pi / 180.0); + NLLIGO::CPrimPoint *point = static_cast(primitive); + point->Point = vPoints.front(); + point->Angle = angle; + break; + } + case NLLIGO::CPrimitiveClass::Path: + { + NLLIGO::CPrimPath *path = static_cast(primitive); + path->VPoints = vPoints; + break; + } + case NLLIGO::CPrimitiveClass::Zone: + { + NLLIGO::CPrimZone *zone = static_cast(primitive); + zone->VPoints = vPoints; + break; + } + } + } +} + +QList AbstractWorldItemCommand::graphicsItemsToPaths(const QList &items, PrimitivesTreeModel *model) +{ + QList result; + Q_FOREACH(QGraphicsItem *item, items) + { + Node *node = qvariant_cast(item->data(Constants::WORLD_EDITOR_NODE)); + result.push_back(model->pathFromNode(node)); + } + return result; +} + +MoveWorldItemsCommand::MoveWorldItemsCommand(const QList &items, const QPointF &offset, + WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) + : AbstractWorldItemCommand(items, scene, model, parent), + m_offset(offset) +{ + setText(QObject::tr("Move item(s)")); +} + +MoveWorldItemsCommand::~MoveWorldItemsCommand() +{ +} + +void MoveWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) +{ + item->moveBy(-m_offset.x(), -m_offset.y()); +} + +void MoveWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) +{ + item->moveBy(m_offset.x(), m_offset.y()); +} + +RotateWorldItemsCommand::RotateWorldItemsCommand(const QList &items, const qreal angle, + const QPointF &pivot, WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) + : AbstractWorldItemCommand(items, scene, model, parent), + m_angle(angle), + m_pivot(pivot) +{ + setText(QObject::tr("Rotate item(s)")); +} + +RotateWorldItemsCommand::~RotateWorldItemsCommand() +{ +} + +void RotateWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) +{ + item->rotateOn(m_pivot, -m_angle); +} + +void RotateWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) +{ + item->rotateOn(m_pivot, m_angle); +} + +ScaleWorldItemsCommand::ScaleWorldItemsCommand(const QList &items, const QPointF &factor, + const QPointF &pivot, WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) + : AbstractWorldItemCommand(items, scene, model, parent), + m_factor(factor), + m_pivot(pivot) +{ + setText(QObject::tr("Scale item(s)")); +} + +ScaleWorldItemsCommand::~ScaleWorldItemsCommand() +{ +} + +void ScaleWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) +{ + QPointF m_invertFactor(1 / m_factor.x(), 1 / m_factor.y()); + item->scaleOn(m_pivot, m_invertFactor); +} + +void ScaleWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) +{ + item->scaleOn(m_pivot, m_factor); +} + +TurnWorldItemsCommand::TurnWorldItemsCommand(const QList &items, const qreal angle, + WorldEditorScene *scene, PrimitivesTreeModel *model, QUndoCommand *parent) + : AbstractWorldItemCommand(items, scene, model, parent), + m_angle(angle) +{ + setText(QObject::tr("Turn item(s)")); +} + +TurnWorldItemsCommand::~TurnWorldItemsCommand() +{ +} + +void TurnWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) +{ + item->turnOn(-m_angle); +} + +void TurnWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) +{ + item->turnOn(m_angle); +} + +ShapeWorldItemsCommand::ShapeWorldItemsCommand(const QList &items, const QList &polygons, + WorldEditorScene *scene, PrimitivesTreeModel *model, + QUndoCommand *parent) + : AbstractWorldItemCommand(items, scene, model, parent), + m_redoPolygons(polygons), + m_undoPolygons(polygonsFromItems(items)) +{ + setText(QObject::tr("Change shape")); +} + +ShapeWorldItemsCommand::~ShapeWorldItemsCommand() +{ +} + +void ShapeWorldItemsCommand::undoChangeItem(int i, AbstractWorldItem *item) +{ + item->setPolygon(m_redoPolygons.at(i)); +} + +void ShapeWorldItemsCommand::redoChangeItem(int i, AbstractWorldItem *item) +{ + item->setPolygon(m_undoPolygons.at(i)); +} + +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp index f9eb7ce54..7401f49fb 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_misc.cpp @@ -1,666 +1,666 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_misc.h" - -// NeL includes -#include -#include -#include -#include -#include -#include -#include - - -// Qt includes - -namespace WorldEditor -{ -namespace Utils -{ - -void syntaxError(const char *filename, xmlNodePtr xmlNode, const char *format, ...) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - nlerror("(%s), node (%s), line (%s) :\n%s", filename, xmlNode->name, xmlNode->content, buffer); -} - -bool getPropertyString(std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) -{ - // Call the CIXml version - if (!NLMISC::CIXml::getPropertyString(result, xmlNode, propName)) - { - // Output a formated error - syntaxError(filename, xmlNode, "Missing XML node property (%s)", propName); - return false; - } - return true; -} - -uint32 getUniqueId() -{ - // Wait 1 ms - sint64 time = NLMISC::CTime::getLocalTime (); - sint64 time2; - while ((time2 = NLMISC::CTime::getLocalTime ()) == time) - { - } - - return (uint32)time2; -} - -bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList) -{ - bool result = false; - - // Load the document - NLMISC::CIFile file; - if (file.open(fileName)) - { - try - { - // Load the document in XML - NLMISC::CIXml xml; - xml.init(file); - - // Get root node - xmlNodePtr rootNode = xml.getRootNode(); - if (rootNode) - { - // Good header ? - if (strcmp((const char *)(rootNode->name), "NEL_WORLD_EDITOR_PROJECT") == 0) - { - int version = -1; - - // Read the parameters - xmlNodePtr node = NLMISC::CIXml::getFirstChildNode(rootNode, "VERSION"); - if (node) - { - std::string versionString; - if (NLMISC::CIXml::getContentString (versionString, node)) - version = atoi(versionString.c_str ()); - } - - if (version == -1) - syntaxError(fileName.c_str(), rootNode, "No version node"); - else - { - // Old format, - if (version <= 1) - { - syntaxError(fileName.c_str(), rootNode, "Old version node"); - } - else - { - // Read it - if (version > WORLD_EDITOR_FILE_VERSION) - { - syntaxError(fileName.c_str(), node, "Unknown file version"); - } - else - { - // Read data directory - node = NLMISC::CIXml::getFirstChildNode(rootNode, "DATA_DIRECTORY"); - if (node) - { - std::string dataDir; - NLMISC::CIXml::getPropertyString(dataDir, node, "VALUE"); - worldEditList.push_back(WorldEditItem(DataDirectoryType, dataDir)); - } - - // Read data directory - node = NLMISC::CIXml::getFirstChildNode(rootNode, "CONTEXT"); - if (node) - { - std::string context; - NLMISC::CIXml::getPropertyString(context, node, "VALUE"); - worldEditList.push_back(WorldEditItem(ContextType, context)); - } - - // Read the database element - node = NLMISC::CIXml::getFirstChildNode(rootNode, "DATABASE_ELEMENT"); - if (node) - { - do - { - // Get the type - std::string type; - if (getPropertyString(type, fileName.c_str(), node, "TYPE")) - { - // Read the filename - std::string filenameChild; - if (getPropertyString(filenameChild, fileName.c_str(), node, "FILENAME")) - { - // Is it a landscape ? - if (type == "landscape") - { - worldEditList.push_back(WorldEditItem(LandscapeType, filenameChild)); - - // Get the primitives - xmlNodePtr primitives = NLMISC::CIXml::getFirstChildNode(node, "PRIMITIVES"); - if (primitives) - { - NLLIGO::CPrimitives ligoPrimitives; - - // Read it - ligoPrimitives.read(primitives, fileName.c_str(), *ligoConfig()); - //_DataHierarchy.back ().Primitives.read (primitives, filename, theApp.Config); - - // Set the filename - //_DataHierarchy.back ().Filename = filenameChild; - } - } - else - { - worldEditList.push_back(WorldEditItem(PrimitiveType, filenameChild)); - } - - } - } - } - while (node = NLMISC::CIXml::getNextChildNode(node, "DATABASE_ELEMENT")); - } - - // Done - result = true; - } - } - } - } - else - { - // Error - syntaxError(fileName.c_str(), rootNode, "Unknown file header : %s", rootNode->name); - } - } - } - catch (NLMISC::Exception &e) - { - nlerror("Error reading file %s : %s", fileName.c_str(), e.what()); - } - } - else - nlerror("Can't open the file %s for reading.", fileName.c_str()); - - return result; -} - -NLLIGO::IPrimitive *getRootPrimitive(NLLIGO::IPrimitive *primitive) -{ - nlassert(primitive); - - if (primitive->getParent() == NULL) - return primitive; - else - return getRootPrimitive(primitive->getParent()); -} - -void initPrimitiveParameters(const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, - const std::vector &initParameters) -{ - // Other parameters - for (uint p = 0; p < initParameters.size(); ++p) - { - // The property - const NLLIGO::CPrimitiveClass::CInitParameters ¶meter = initParameters[p]; - - // Look for it in the class - uint cp; - for (cp = 0; cp < primClass.Parameters.size(); ++cp) - { - // Good one ? - if (primClass.Parameters[cp].Name == initParameters[p].Name) - break; - } - - // The primitive type - NLLIGO::CPrimitiveClass::CParameter::TType type; - - // Found ? - if (cp < primClass.Parameters.size()) - type = primClass.Parameters[cp].Type; - - if (initParameters[p].Name == "name") - type = NLLIGO::CPrimitiveClass::CParameter::String; - - if (cp < primClass.Parameters.size () || (initParameters[p].Name == "name")) - { - // Default value ? - if (!parameter.DefaultValue.empty()) - { - // Type of property - switch (type) - { - case NLLIGO::CPrimitiveClass::CParameter::Boolean: - case NLLIGO::CPrimitiveClass::CParameter::ConstString: - case NLLIGO::CPrimitiveClass::CParameter::String: - { - // Some feedback - if (parameter.DefaultValue.size() > 1) - nlerror("Warning: parameter (%s) in class name (%s) has more than 1 default value (%d).", - parameter.Name.c_str(), primClass.Name.c_str(), parameter.DefaultValue.size()); - - if ((cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) - || parameter.DefaultValue[0].GenID) - { - // Remove this property - primitive.removePropertyByName(parameter.Name.c_str()); - - // Add this property - primitive.addPropertyByName(parameter.Name.c_str(), - new NLLIGO::CPropertyString((parameter.DefaultValue[0].GenID ? NLMISC::toString(getUniqueId()) : "").c_str ())); - } - break; - } - case NLLIGO::CPrimitiveClass::CParameter::ConstStringArray: - case NLLIGO::CPrimitiveClass::CParameter::StringArray: - { - bool Visible = false; - if (cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) - Visible = true; - for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) - { - // Generate a unique id ? - if (parameter.DefaultValue[i].GenID) - Visible = true; - } - if (Visible) - { - // Remove this property - primitive.removePropertyByName (parameter.Name.c_str()); - - // Add this property - NLLIGO::CPropertyStringArray *str = new NLLIGO::CPropertyStringArray(); - str->StringArray.resize (parameter.DefaultValue.size()); - for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) - { - // Generate a unique id ? - if (parameter.DefaultValue[i].GenID) - str->StringArray[i] = NLMISC::toString(getUniqueId()); - else - str->StringArray[i] = ""; - } - primitive.addPropertyByName(parameter.Name.c_str(), str); - } - break; - } - } - } - } - else - { - // Some feedback - nlerror("Warning: parameter (%s) doesn't exist in class (%s).", - initParameters[p].Name.c_str(), primClass.Name.c_str()); - } - } -} - -NLLIGO::IPrimitive *createPrimitive(const char *className, const char *primName, - const NLMISC::CVector &initPos, float deltaPos, - const std::vector &initParameters, - NLLIGO::IPrimitive *parent) -{ - // Get the prim class - const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(className); - if (primClass) - { - // Create the base primitive - NLLIGO::IPrimitive *primitive = NULL; - switch (primClass->Type) - { - case NLLIGO::CPrimitiveClass::Node: - primitive = new NLLIGO::CPrimNode; - break; - case NLLIGO::CPrimitiveClass::Point: - { - NLLIGO::CPrimPoint *point = new NLLIGO::CPrimPoint; - primitive = point; - point->Point.CVector::operator = (initPos); - } - break; - case NLLIGO::CPrimitiveClass::Path: - { - NLLIGO::CPrimPath *path = new NLLIGO::CPrimPath; - primitive = path; - path->VPoints.push_back(NLLIGO::CPrimVector(initPos)); - NLMISC::CVector secondPos = NLMISC::CVector(initPos.x + deltaPos, initPos.y, 0.0); - path->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); - break; - } - case NLLIGO::CPrimitiveClass::Zone: - { - NLLIGO::CPrimZone *zone = new NLLIGO::CPrimZone; - primitive = zone; - zone->VPoints.push_back(NLLIGO::CPrimVector(initPos)); - NLMISC::CVector secondPos = NLMISC::CVector(initPos.x + deltaPos, initPos.y, 0.0); - zone->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); - secondPos.y = initPos.y + deltaPos; - zone->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); - break; - } - case NLLIGO::CPrimitiveClass::Alias: - primitive = new NLLIGO::CPrimAlias; - break; - case NLLIGO::CPrimitiveClass::Bitmap: - primitive = new NLLIGO::CPrimNode; - break; - } - nlassert(primitive); - - // Add properties - primitive->addPropertyByName("class", new NLLIGO::CPropertyString(className)); - primitive->addPropertyByName("name", new NLLIGO::CPropertyString(primName, primName[0] == 0)); - - // Init with default parameters - std::vector tempParam; - tempParam.reserve(primClass->Parameters.size()); - for (size_t i = 0; i < primClass->Parameters.size(); i++) - tempParam.push_back (primClass->Parameters[i]); - initPrimitiveParameters (*primClass, *primitive, tempParam); - - // Init with option parameters - initPrimitiveParameters(*primClass, *primitive, initParameters); - - parent->insertChild(primitive); - /* - // Insert the primitive - insertPrimitive (locator, primitive); - */ - // The new pos - NLMISC::CVector newPos = initPos; - newPos.x += deltaPos; - - // Create static children - uint c; - for (c = 0; c < primClass->StaticChildren.size(); c++) - { - // The child ref - const NLLIGO::CPrimitiveClass::CChild &child = primClass->StaticChildren[c]; - - // Create the child - const NLLIGO::IPrimitive *childPrim = createPrimitive(child.ClassName.c_str(), child.Name.c_str(), - newPos, deltaPos, primClass->StaticChildren[c].Parameters, primitive); - - // The new pos - newPos.y += deltaPos; - } - - // Canceled ? - if (c < primClass->StaticChildren.size()) - { - deletePrimitive(primitive); - return NULL; - } - - if (primitive) - { - if (!primClass->AutoInit) - { - // TODO - } - - // Eval the default name property - std::string name; - if (!primitive->getPropertyByName ("name", name) || name.empty()) - { - const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(*primitive); - if (primClass) - { - for (size_t i = 0; i < primClass->Parameters.size(); ++i) - { - if (primClass->Parameters[i].Name == "name") - { - std::string result; - primClass->Parameters[i].getDefaultValue(result, *primitive, *primClass, NULL); - if (!result.empty()) - { - primitive->removePropertyByName("name"); - primitive->addPropertyByName("name", new NLLIGO::CPropertyString(result.c_str(), true)); - } - } - } - } - } - - primitive->initDefaultValues(*ligoConfig()); - } - return primitive; - } - else - nlerror("Unknown primitive class name : %s", className); - - return 0; -} - -void deletePrimitive(NLLIGO::IPrimitive *primitive) -{ - // Get the parent - NLLIGO::IPrimitive *parent = primitive->getParent(); - nlassert(parent); - - // Get the child id - uint childId; - nlverify(parent->getChildId(childId, primitive)); - - // Delete the child - nlverify(parent->removeChild(childId)); -} - -bool updateDefaultValues(NLLIGO::IPrimitive *primitive) -{ - bool modified = false; - - // Get the prim class - const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(*primitive); - nlassert(primClass); - - if (primClass) - { - // For each parameters - for (uint i = 0; i < primClass->Parameters.size(); i++) - { - // First check the primitive property has to good type - NLLIGO::IProperty *prop; - if (primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), prop)) - { - // String to array ? - NLLIGO::CPropertyString *propString = dynamic_cast(prop); - const bool classStringArray = primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray || - primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray; - if (propString && classStringArray) - { - // Build an array string - std::vector strings; - if (!propString->String.empty()) - strings.push_back(propString->String); - prop = new NLLIGO::CPropertyStringArray(strings); - primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); - modified = true; - } - - // Array to string ? - NLLIGO::CPropertyStringArray *propStringArray = dynamic_cast(prop); - if (propStringArray && !classStringArray) - { - // Build an array string - std::string str; - if (!propStringArray->StringArray.empty()) - str = propStringArray->StringArray[0]; - prop = new NLLIGO::CPropertyString(str); - primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); - modified = true; - } - } - - // String or string array ? - if (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::String) - { - // Default value available ? - if (!primClass->Parameters[i].DefaultValue.empty ()) - { - // Unique Id ? - if (primClass->Parameters[i].DefaultValue[0].GenID) - { - // The doesn't exist ? - std::string result; - if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) - { - // Add it ! - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString(NLMISC::toString(getUniqueId()).c_str())); - modified = true; - } - } - // Hidden ? - else if (!primClass->Parameters[i].Visible) - { - // The doesn't exist ? - std::string result; - if (!primitive->getPropertyByName (primClass->Parameters[i].Name.c_str (), result)) - { - // Add it ! - primitive->addPropertyByName (primClass->Parameters[i].Name.c_str (), new NLLIGO::CPropertyString ("")); - modified = true; - } - } - } - } - else if ((primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray) || - (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray)) - { - for (uint j = 0; j < primClass->Parameters[i].DefaultValue.size(); j++) - { - // Unique Id ? - if (primClass->Parameters[i].DefaultValue[j].GenID) - { - // The doesn't exist ? - std::vector result; - std::vector *resultPtr = NULL; - if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || - (resultPtr->size() <= j)) - { - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size() <= j) - result.resize(j + 1); - - // Resize to it - primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); - - // Set the value - result[j] = NLMISC::toString(getUniqueId()); - - // Add the new property array - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); - modified = true; - } - } - // Hidden ? - else if (!primClass->Parameters[i].Visible) - { - // The doesn't exist ? - std::vector result; - std::vector *resultPtr = NULL; - if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || (resultPtr->size () <= j)) - { - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size() <= j) - result.resize(j + 1); - - // Resize to it - primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); - - // Set the value - result[j] = ""; - - // Add the new property array - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); - modified = true; - } - } - } - } - else - { - // Default value available ? - if (!primClass->Parameters[i].DefaultValue.empty ()) - { - // Hidden ? - if (!primClass->Parameters[i].Visible) - { - // The doesn't exist ? - std::string result; - if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) - { - // Add it ! - primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString("")); - modified = true; - } - } - } - } - } - } - return modified; -} - -bool recursiveUpdateDefaultValues(NLLIGO::IPrimitive *primitive) -{ - bool modified = updateDefaultValues(primitive); - - const uint count = primitive->getNumChildren(); - for (uint i = 0; i < count; ++i) - { - // Get the child - NLLIGO::IPrimitive *child; - nlverify(primitive->getChild(child, i)); - modified |= recursiveUpdateDefaultValues(child); - } - - return modified; -} - -NLLIGO::CLigoConfig *ligoConfig() -{ - return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig; -} - -} /* namespace Utils */ -} /* namespace WorldEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_misc.h" + +// NeL includes +#include +#include +#include +#include +#include +#include +#include + + +// Qt includes + +namespace WorldEditor +{ +namespace Utils +{ + +void syntaxError(const char *filename, xmlNodePtr xmlNode, const char *format, ...) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + nlerror("(%s), node (%s), line (%s) :\n%s", filename, xmlNode->name, xmlNode->content, buffer); +} + +bool getPropertyString(std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) +{ + // Call the CIXml version + if (!NLMISC::CIXml::getPropertyString(result, xmlNode, propName)) + { + // Output a formated error + syntaxError(filename, xmlNode, "Missing XML node property (%s)", propName); + return false; + } + return true; +} + +uint32 getUniqueId() +{ + // Wait 1 ms + sint64 time = NLMISC::CTime::getLocalTime (); + sint64 time2; + while ((time2 = NLMISC::CTime::getLocalTime ()) == time) + { + } + + return (uint32)time2; +} + +bool loadWorldEditFile(const std::string &fileName, WorldEditList &worldEditList) +{ + bool result = false; + + // Load the document + NLMISC::CIFile file; + if (file.open(fileName)) + { + try + { + // Load the document in XML + NLMISC::CIXml xml; + xml.init(file); + + // Get root node + xmlNodePtr rootNode = xml.getRootNode(); + if (rootNode) + { + // Good header ? + if (strcmp((const char *)(rootNode->name), "NEL_WORLD_EDITOR_PROJECT") == 0) + { + int version = -1; + + // Read the parameters + xmlNodePtr node = NLMISC::CIXml::getFirstChildNode(rootNode, "VERSION"); + if (node) + { + std::string versionString; + if (NLMISC::CIXml::getContentString (versionString, node)) + version = atoi(versionString.c_str ()); + } + + if (version == -1) + syntaxError(fileName.c_str(), rootNode, "No version node"); + else + { + // Old format, + if (version <= 1) + { + syntaxError(fileName.c_str(), rootNode, "Old version node"); + } + else + { + // Read it + if (version > WORLD_EDITOR_FILE_VERSION) + { + syntaxError(fileName.c_str(), node, "Unknown file version"); + } + else + { + // Read data directory + node = NLMISC::CIXml::getFirstChildNode(rootNode, "DATA_DIRECTORY"); + if (node) + { + std::string dataDir; + NLMISC::CIXml::getPropertyString(dataDir, node, "VALUE"); + worldEditList.push_back(WorldEditItem(DataDirectoryType, dataDir)); + } + + // Read data directory + node = NLMISC::CIXml::getFirstChildNode(rootNode, "CONTEXT"); + if (node) + { + std::string context; + NLMISC::CIXml::getPropertyString(context, node, "VALUE"); + worldEditList.push_back(WorldEditItem(ContextType, context)); + } + + // Read the database element + node = NLMISC::CIXml::getFirstChildNode(rootNode, "DATABASE_ELEMENT"); + if (node) + { + do + { + // Get the type + std::string type; + if (getPropertyString(type, fileName.c_str(), node, "TYPE")) + { + // Read the filename + std::string filenameChild; + if (getPropertyString(filenameChild, fileName.c_str(), node, "FILENAME")) + { + // Is it a landscape ? + if (type == "landscape") + { + worldEditList.push_back(WorldEditItem(LandscapeType, filenameChild)); + + // Get the primitives + xmlNodePtr primitives = NLMISC::CIXml::getFirstChildNode(node, "PRIMITIVES"); + if (primitives) + { + NLLIGO::CPrimitives ligoPrimitives; + + // Read it + ligoPrimitives.read(primitives, fileName.c_str(), *ligoConfig()); + //_DataHierarchy.back ().Primitives.read (primitives, filename, theApp.Config); + + // Set the filename + //_DataHierarchy.back ().Filename = filenameChild; + } + } + else + { + worldEditList.push_back(WorldEditItem(PrimitiveType, filenameChild)); + } + + } + } + } + while (node = NLMISC::CIXml::getNextChildNode(node, "DATABASE_ELEMENT")); + } + + // Done + result = true; + } + } + } + } + else + { + // Error + syntaxError(fileName.c_str(), rootNode, "Unknown file header : %s", rootNode->name); + } + } + } + catch (NLMISC::Exception &e) + { + nlerror("Error reading file %s : %s", fileName.c_str(), e.what()); + } + } + else + nlerror("Can't open the file %s for reading.", fileName.c_str()); + + return result; +} + +NLLIGO::IPrimitive *getRootPrimitive(NLLIGO::IPrimitive *primitive) +{ + nlassert(primitive); + + if (primitive->getParent() == NULL) + return primitive; + else + return getRootPrimitive(primitive->getParent()); +} + +void initPrimitiveParameters(const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, + const std::vector &initParameters) +{ + // Other parameters + for (uint p = 0; p < initParameters.size(); ++p) + { + // The property + const NLLIGO::CPrimitiveClass::CInitParameters ¶meter = initParameters[p]; + + // Look for it in the class + uint cp; + for (cp = 0; cp < primClass.Parameters.size(); ++cp) + { + // Good one ? + if (primClass.Parameters[cp].Name == initParameters[p].Name) + break; + } + + // The primitive type + NLLIGO::CPrimitiveClass::CParameter::TType type; + + // Found ? + if (cp < primClass.Parameters.size()) + type = primClass.Parameters[cp].Type; + + if (initParameters[p].Name == "name") + type = NLLIGO::CPrimitiveClass::CParameter::String; + + if (cp < primClass.Parameters.size () || (initParameters[p].Name == "name")) + { + // Default value ? + if (!parameter.DefaultValue.empty()) + { + // Type of property + switch (type) + { + case NLLIGO::CPrimitiveClass::CParameter::Boolean: + case NLLIGO::CPrimitiveClass::CParameter::ConstString: + case NLLIGO::CPrimitiveClass::CParameter::String: + { + // Some feedback + if (parameter.DefaultValue.size() > 1) + nlerror("Warning: parameter (%s) in class name (%s) has more than 1 default value (%d).", + parameter.Name.c_str(), primClass.Name.c_str(), parameter.DefaultValue.size()); + + if ((cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) + || parameter.DefaultValue[0].GenID) + { + // Remove this property + primitive.removePropertyByName(parameter.Name.c_str()); + + // Add this property + primitive.addPropertyByName(parameter.Name.c_str(), + new NLLIGO::CPropertyString((parameter.DefaultValue[0].GenID ? NLMISC::toString(getUniqueId()) : "").c_str ())); + } + break; + } + case NLLIGO::CPrimitiveClass::CParameter::ConstStringArray: + case NLLIGO::CPrimitiveClass::CParameter::StringArray: + { + bool Visible = false; + if (cp < primClass.Parameters.size() && !primClass.Parameters[cp].Visible) + Visible = true; + for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) + { + // Generate a unique id ? + if (parameter.DefaultValue[i].GenID) + Visible = true; + } + if (Visible) + { + // Remove this property + primitive.removePropertyByName (parameter.Name.c_str()); + + // Add this property + NLLIGO::CPropertyStringArray *str = new NLLIGO::CPropertyStringArray(); + str->StringArray.resize (parameter.DefaultValue.size()); + for (size_t i = 0; i < parameter.DefaultValue.size(); ++i) + { + // Generate a unique id ? + if (parameter.DefaultValue[i].GenID) + str->StringArray[i] = NLMISC::toString(getUniqueId()); + else + str->StringArray[i] = ""; + } + primitive.addPropertyByName(parameter.Name.c_str(), str); + } + break; + } + } + } + } + else + { + // Some feedback + nlerror("Warning: parameter (%s) doesn't exist in class (%s).", + initParameters[p].Name.c_str(), primClass.Name.c_str()); + } + } +} + +NLLIGO::IPrimitive *createPrimitive(const char *className, const char *primName, + const NLMISC::CVector &initPos, float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent) +{ + // Get the prim class + const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(className); + if (primClass) + { + // Create the base primitive + NLLIGO::IPrimitive *primitive = NULL; + switch (primClass->Type) + { + case NLLIGO::CPrimitiveClass::Node: + primitive = new NLLIGO::CPrimNode; + break; + case NLLIGO::CPrimitiveClass::Point: + { + NLLIGO::CPrimPoint *point = new NLLIGO::CPrimPoint; + primitive = point; + point->Point.CVector::operator = (initPos); + } + break; + case NLLIGO::CPrimitiveClass::Path: + { + NLLIGO::CPrimPath *path = new NLLIGO::CPrimPath; + primitive = path; + path->VPoints.push_back(NLLIGO::CPrimVector(initPos)); + NLMISC::CVector secondPos = NLMISC::CVector(initPos.x + deltaPos, initPos.y, 0.0); + path->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); + break; + } + case NLLIGO::CPrimitiveClass::Zone: + { + NLLIGO::CPrimZone *zone = new NLLIGO::CPrimZone; + primitive = zone; + zone->VPoints.push_back(NLLIGO::CPrimVector(initPos)); + NLMISC::CVector secondPos = NLMISC::CVector(initPos.x + deltaPos, initPos.y, 0.0); + zone->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); + secondPos.y = initPos.y + deltaPos; + zone->VPoints.push_back(NLLIGO::CPrimVector(secondPos)); + break; + } + case NLLIGO::CPrimitiveClass::Alias: + primitive = new NLLIGO::CPrimAlias; + break; + case NLLIGO::CPrimitiveClass::Bitmap: + primitive = new NLLIGO::CPrimNode; + break; + } + nlassert(primitive); + + // Add properties + primitive->addPropertyByName("class", new NLLIGO::CPropertyString(className)); + primitive->addPropertyByName("name", new NLLIGO::CPropertyString(primName, primName[0] == 0)); + + // Init with default parameters + std::vector tempParam; + tempParam.reserve(primClass->Parameters.size()); + for (size_t i = 0; i < primClass->Parameters.size(); i++) + tempParam.push_back (primClass->Parameters[i]); + initPrimitiveParameters (*primClass, *primitive, tempParam); + + // Init with option parameters + initPrimitiveParameters(*primClass, *primitive, initParameters); + + parent->insertChild(primitive); + /* + // Insert the primitive + insertPrimitive (locator, primitive); + */ + // The new pos + NLMISC::CVector newPos = initPos; + newPos.x += deltaPos; + + // Create static children + uint c; + for (c = 0; c < primClass->StaticChildren.size(); c++) + { + // The child ref + const NLLIGO::CPrimitiveClass::CChild &child = primClass->StaticChildren[c]; + + // Create the child + const NLLIGO::IPrimitive *childPrim = createPrimitive(child.ClassName.c_str(), child.Name.c_str(), + newPos, deltaPos, primClass->StaticChildren[c].Parameters, primitive); + + // The new pos + newPos.y += deltaPos; + } + + // Canceled ? + if (c < primClass->StaticChildren.size()) + { + deletePrimitive(primitive); + return NULL; + } + + if (primitive) + { + if (!primClass->AutoInit) + { + // TODO + } + + // Eval the default name property + std::string name; + if (!primitive->getPropertyByName ("name", name) || name.empty()) + { + const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(*primitive); + if (primClass) + { + for (size_t i = 0; i < primClass->Parameters.size(); ++i) + { + if (primClass->Parameters[i].Name == "name") + { + std::string result; + primClass->Parameters[i].getDefaultValue(result, *primitive, *primClass, NULL); + if (!result.empty()) + { + primitive->removePropertyByName("name"); + primitive->addPropertyByName("name", new NLLIGO::CPropertyString(result.c_str(), true)); + } + } + } + } + } + + primitive->initDefaultValues(*ligoConfig()); + } + return primitive; + } + else + nlerror("Unknown primitive class name : %s", className); + + return 0; +} + +void deletePrimitive(NLLIGO::IPrimitive *primitive) +{ + // Get the parent + NLLIGO::IPrimitive *parent = primitive->getParent(); + nlassert(parent); + + // Get the child id + uint childId; + nlverify(parent->getChildId(childId, primitive)); + + // Delete the child + nlverify(parent->removeChild(childId)); +} + +bool updateDefaultValues(NLLIGO::IPrimitive *primitive) +{ + bool modified = false; + + // Get the prim class + const NLLIGO::CPrimitiveClass *primClass = ligoConfig()->getPrimitiveClass(*primitive); + nlassert(primClass); + + if (primClass) + { + // For each parameters + for (uint i = 0; i < primClass->Parameters.size(); i++) + { + // First check the primitive property has to good type + NLLIGO::IProperty *prop; + if (primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), prop)) + { + // String to array ? + NLLIGO::CPropertyString *propString = dynamic_cast(prop); + const bool classStringArray = primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray || + primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray; + if (propString && classStringArray) + { + // Build an array string + std::vector strings; + if (!propString->String.empty()) + strings.push_back(propString->String); + prop = new NLLIGO::CPropertyStringArray(strings); + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); + modified = true; + } + + // Array to string ? + NLLIGO::CPropertyStringArray *propStringArray = dynamic_cast(prop); + if (propStringArray && !classStringArray) + { + // Build an array string + std::string str; + if (!propStringArray->StringArray.empty()) + str = propStringArray->StringArray[0]; + prop = new NLLIGO::CPropertyString(str); + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), prop); + modified = true; + } + } + + // String or string array ? + if (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::String) + { + // Default value available ? + if (!primClass->Parameters[i].DefaultValue.empty ()) + { + // Unique Id ? + if (primClass->Parameters[i].DefaultValue[0].GenID) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) + { + // Add it ! + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString(NLMISC::toString(getUniqueId()).c_str())); + modified = true; + } + } + // Hidden ? + else if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName (primClass->Parameters[i].Name.c_str (), result)) + { + // Add it ! + primitive->addPropertyByName (primClass->Parameters[i].Name.c_str (), new NLLIGO::CPropertyString ("")); + modified = true; + } + } + } + } + else if ((primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::StringArray) || + (primClass->Parameters[i].Type == NLLIGO::CPrimitiveClass::CParameter::ConstStringArray)) + { + for (uint j = 0; j < primClass->Parameters[i].DefaultValue.size(); j++) + { + // Unique Id ? + if (primClass->Parameters[i].DefaultValue[j].GenID) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || + (resultPtr->size() <= j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size() <= j) + result.resize(j + 1); + + // Resize to it + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + + // Set the value + result[j] = NLMISC::toString(getUniqueId()); + + // Add the new property array + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); + modified = true; + } + } + // Hidden ? + else if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), resultPtr) || (resultPtr->size () <= j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size() <= j) + result.resize(j + 1); + + // Resize to it + primitive->removePropertyByName(primClass->Parameters[i].Name.c_str()); + + // Set the value + result[j] = ""; + + // Add the new property array + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyStringArray(result)); + modified = true; + } + } + } + } + else + { + // Default value available ? + if (!primClass->Parameters[i].DefaultValue.empty ()) + { + // Hidden ? + if (!primClass->Parameters[i].Visible) + { + // The doesn't exist ? + std::string result; + if (!primitive->getPropertyByName(primClass->Parameters[i].Name.c_str(), result)) + { + // Add it ! + primitive->addPropertyByName(primClass->Parameters[i].Name.c_str(), new NLLIGO::CPropertyString("")); + modified = true; + } + } + } + } + } + } + return modified; +} + +bool recursiveUpdateDefaultValues(NLLIGO::IPrimitive *primitive) +{ + bool modified = updateDefaultValues(primitive); + + const uint count = primitive->getNumChildren(); + for (uint i = 0; i < count; ++i) + { + // Get the child + NLLIGO::IPrimitive *child; + nlverify(primitive->getChild(child, i)); + modified |= recursiveUpdateDefaultValues(child); + } + + return modified; +} + +NLLIGO::CLigoConfig *ligoConfig() +{ + return NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig; +} + +} /* namespace Utils */ +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp index aa995777a..fe7dc45c1 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_plugin.cpp @@ -1,136 +1,136 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_plugin.h" -#include "world_editor_window.h" -#include "world_editor_settings_page.h" - -#include "../core/icore.h" -#include "../core/core_constants.h" - -// NeL includes -#include "nel/misc/debug.h" -#include -#include -#include - -// Qt includes -#include - -namespace WorldEditor -{ - -WorldEditorPlugin::~WorldEditorPlugin() -{ - Q_FOREACH(QObject *obj, m_autoReleaseObjects) - { - m_plugMan->removeObject(obj); - } - qDeleteAll(m_autoReleaseObjects); - m_autoReleaseObjects.clear(); -} - -bool WorldEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) -{ - m_plugMan = pluginManager; - - WorldEditorSettingsPage *weSettings = new WorldEditorSettingsPage(this); - addAutoReleasedObject(weSettings); - - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Constants::WORLD_EDITOR_SECTION); - m_ligoConfig.CellSize = settings->value(Constants::WORLD_EDITOR_CELL_SIZE, "160").toFloat(); - m_ligoConfig.Snap = settings->value(Constants::WORLD_EDITOR_SNAP, "1").toFloat(); - m_ligoConfig.ZoneSnapShotRes = settings->value(Constants::ZONE_SNAPSHOT_RES, "128").toUInt(); - QString fileName = settings->value(Constants::PRIMITIVE_CLASS_FILENAME, "world_editor_classes.xml").toString(); - settings->endGroup(); - try - { - // Search path of file world_editor_classes.xml - std::string ligoPath = NLMISC::CPath::lookup(fileName.toStdString()); - // Init LIGO - m_ligoConfig.readPrimitiveClass(ligoPath.c_str(), true); - NLLIGO::Register(); - NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig; - } - catch (NLMISC::Exception &e) - { - *errorString = tr("(%1)").arg(e.what()); - return false; - } - - // Reset - m_ligoConfig.resetPrimitiveConfiguration (); - - // TODO: get file names! from settings - m_ligoConfig.readPrimitiveClass("world_editor_primitive_configuration.xml", true); - - - addAutoReleasedObject(new WorldEditorContext(this)); - return true; -} - -void WorldEditorPlugin::extensionsInitialized() -{ -} - -void WorldEditorPlugin::shutdown() -{ -} - -void WorldEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) -{ -#ifdef NL_OS_WINDOWS - // Ensure that a context doesn't exist yet. - // This only applies to platforms without PIC, e.g. Windows. - nlassert(!NLMISC::INelContext::isContextInitialised()); -#endif // NL_OS_WINDOWS - m_libContext = new NLMISC::CLibraryContext(*nelContext); -} - -void WorldEditorPlugin::addAutoReleasedObject(QObject *obj) -{ - m_plugMan->addObject(obj); - m_autoReleaseObjects.prepend(obj); -} - -WorldEditorContext::WorldEditorContext(QObject *parent) - : IContext(parent), - m_worldEditorWindow(0) -{ - m_worldEditorWindow = new WorldEditorWindow(); -} - -QUndoStack *WorldEditorContext::undoStack() -{ - return m_worldEditorWindow->undoStack(); -} - -void WorldEditorContext::open() -{ - m_worldEditorWindow->open(); -} - -QWidget *WorldEditorContext::widget() -{ - return m_worldEditorWindow; -} - -} - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_plugin.h" +#include "world_editor_window.h" +#include "world_editor_settings_page.h" + +#include "../core/icore.h" +#include "../core/core_constants.h" + +// NeL includes +#include "nel/misc/debug.h" +#include +#include +#include + +// Qt includes +#include + +namespace WorldEditor +{ + +WorldEditorPlugin::~WorldEditorPlugin() +{ + Q_FOREACH(QObject *obj, m_autoReleaseObjects) + { + m_plugMan->removeObject(obj); + } + qDeleteAll(m_autoReleaseObjects); + m_autoReleaseObjects.clear(); +} + +bool WorldEditorPlugin::initialize(ExtensionSystem::IPluginManager *pluginManager, QString *errorString) +{ + m_plugMan = pluginManager; + + WorldEditorSettingsPage *weSettings = new WorldEditorSettingsPage(this); + addAutoReleasedObject(weSettings); + + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::WORLD_EDITOR_SECTION); + m_ligoConfig.CellSize = settings->value(Constants::WORLD_EDITOR_CELL_SIZE, "160").toFloat(); + m_ligoConfig.Snap = settings->value(Constants::WORLD_EDITOR_SNAP, "1").toFloat(); + m_ligoConfig.ZoneSnapShotRes = settings->value(Constants::ZONE_SNAPSHOT_RES, "128").toUInt(); + QString fileName = settings->value(Constants::PRIMITIVE_CLASS_FILENAME, "world_editor_classes.xml").toString(); + settings->endGroup(); + try + { + // Search path of file world_editor_classes.xml + std::string ligoPath = NLMISC::CPath::lookup(fileName.toStdString()); + // Init LIGO + m_ligoConfig.readPrimitiveClass(ligoPath.c_str(), true); + NLLIGO::Register(); + NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &m_ligoConfig; + } + catch (NLMISC::Exception &e) + { + *errorString = tr("(%1)").arg(e.what()); + return false; + } + + // Reset + m_ligoConfig.resetPrimitiveConfiguration (); + + // TODO: get file names! from settings + m_ligoConfig.readPrimitiveClass("world_editor_primitive_configuration.xml", true); + + + addAutoReleasedObject(new WorldEditorContext(this)); + return true; +} + +void WorldEditorPlugin::extensionsInitialized() +{ +} + +void WorldEditorPlugin::shutdown() +{ +} + +void WorldEditorPlugin::setNelContext(NLMISC::INelContext *nelContext) +{ +#ifdef NL_OS_WINDOWS + // Ensure that a context doesn't exist yet. + // This only applies to platforms without PIC, e.g. Windows. + nlassert(!NLMISC::INelContext::isContextInitialised()); +#endif // NL_OS_WINDOWS + m_libContext = new NLMISC::CLibraryContext(*nelContext); +} + +void WorldEditorPlugin::addAutoReleasedObject(QObject *obj) +{ + m_plugMan->addObject(obj); + m_autoReleaseObjects.prepend(obj); +} + +WorldEditorContext::WorldEditorContext(QObject *parent) + : IContext(parent), + m_worldEditorWindow(0) +{ + m_worldEditorWindow = new WorldEditorWindow(); +} + +QUndoStack *WorldEditorContext::undoStack() +{ + return m_worldEditorWindow->undoStack(); +} + +void WorldEditorContext::open() +{ + m_worldEditorWindow->open(); +} + +QWidget *WorldEditorContext::widget() +{ + return m_worldEditorWindow; +} + +} + Q_EXPORT_PLUGIN(WorldEditor::WorldEditorPlugin) \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp index 678b361fe..b4be9c30e 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene.cpp @@ -1,604 +1,604 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_scene.h" -#include "world_editor_scene_item.h" -#include "world_editor_actions.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include - -namespace WorldEditor -{ - -WorldEditorScene::WorldEditorScene(int sizeCell, PrimitivesTreeModel *model, QUndoStack *undoStack, QObject *parent) - : LandscapeEditor::LandscapeSceneBase(sizeCell, parent), - m_editedSelectedItems(false), - m_lastPickedPrimitive(0), - m_mode(SelectMode), - m_pointsMode(false), - m_undoStack(undoStack), - m_model(model) -{ - setItemIndexMethod(NoIndex); - - // TODO: get params from settings - setSceneRect(QRectF(-20 * 160, -20 * 160, 256 * 160, 256 * 160)); - - m_greenPen.setColor(QColor(50, 255, 155)); - m_greenPen.setWidth(0); - m_greenBrush.setColor(QColor(50, 255, 155, 80)); - m_greenBrush.setStyle(Qt::SolidPattern); - - m_purplePen.setColor(QColor(100, 0, 255)); - m_purplePen.setWidth(0); - m_purpleBrush.setColor(QColor(100, 0, 255, 80)); - m_purpleBrush.setStyle(Qt::SolidPattern); -} - -WorldEditorScene::~WorldEditorScene() -{ -} - -AbstractWorldItem *WorldEditorScene::addWorldItemPoint(const QPointF &point, const qreal angle, - const qreal radius, bool showArrow) -{ - WorldItemPoint *item = new WorldItemPoint(point, angle, radius, showArrow); - addItem(item); - return item; -} - -AbstractWorldItem *WorldEditorScene::addWorldItemPath(const QPolygonF &polyline, bool showArrow) -{ - WorldItemPath *item = new WorldItemPath(polyline); - addItem(item); - return item; -} - -AbstractWorldItem *WorldEditorScene::addWorldItemZone(const QPolygonF &polygon) -{ - WorldItemZone *item = new WorldItemZone(polygon); - addItem(item); - return item; -} - -void WorldEditorScene::removeWorldItem(QGraphicsItem *item) -{ - updateSelectedWorldItems(true); - m_selectedItems.clear(); - m_editedSelectedItems = false; - m_firstSelection = false; - delete item; -} - -void WorldEditorScene::setModeEdit(WorldEditorScene::ModeEdit mode) -{ - if (mode == WorldEditorScene::SelectMode) - m_editedSelectedItems = false; - - m_mode = mode; -} - -WorldEditorScene::ModeEdit WorldEditorScene::editMode() const -{ - return m_mode; -} - -bool WorldEditorScene::isEnabledEditPoints() const -{ - return m_pointsMode; -} - -void WorldEditorScene::setEnabledEditPoints(bool enabled) -{ - if (m_pointsMode == enabled) - return; - - m_pointsMode = enabled; - - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - AbstractWorldItem *worldItem = qgraphicsitem_cast(item); - if (worldItem != 0) - worldItem->setEnabledSubPoints(enabled); - } - - m_selectedPoints.clear(); -} - -void WorldEditorScene::updateSelection(const QList &selected, const QList &deselected) -{ - // Deselect and remove from list graphics items. - Q_FOREACH(QGraphicsItem *item, deselected) - { - // Item is selected? - int i = m_selectedItems.indexOf(item); - if (i != -1) - { - updateSelectedWorldItem(item, false); - m_selectedItems.takeAt(i); - } - } - - // Select and add from list graphics items. - Q_FOREACH(QGraphicsItem *item, selected) - { - // Item is selected? - int i = m_selectedItems.indexOf(item); - if (i == -1) - { - updateSelectedWorldItem(item, true); - m_selectedItems.push_back(item); - } - } - - update(); - m_firstSelection = true; -} - -void WorldEditorScene::drawForeground(QPainter *painter, const QRectF &rect) -{ - QGraphicsScene::drawForeground(painter, rect); - - if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0)) - { - // Draw selection area - if (m_selectionArea.left() < m_selectionArea.right()) - { - painter->setPen(m_greenPen); - painter->setBrush(m_greenBrush); - } - else - { - painter->setPen(m_purplePen); - painter->setBrush(m_purpleBrush); - } - painter->drawRect(m_selectionArea); - } -} - -void WorldEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - m_firstPick = mouseEvent->scenePos(); - - if (isEnabledEditPoints()) - { - m_polygons = polygonsFromItems(m_selectedItems); - - if (mouseEvent->button() == Qt::LeftButton) - { - // Create new sub-points - // Call method mousePressEvent for sub-point located under mouse - LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); - - if ((!m_editedSelectedItems && m_selectedPoints.isEmpty()) || - (!calcBoundingRect(m_selectedPoints).contains(mouseEvent->scenePos()))) - { - updatePickSelectionPoints(mouseEvent->scenePos()); - m_firstSelection = true; - } - m_pivot = calcBoundingRect(m_selectedPoints).center(); - } - else if (mouseEvent->button() == Qt::RightButton) - { - updateSelectedPointItems(false); - m_selectedPoints.clear(); - - // Delete sub-points if it located under mouse - // Call method mousePressEvent for sub-point located under mouse - LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); - } - } - else - { - LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); - - if (mouseEvent->button() != Qt::LeftButton) - return; - - if ((!m_editedSelectedItems && m_selectedItems.isEmpty()) || - (!calcBoundingRect(m_selectedItems).contains(mouseEvent->scenePos()))) - { - updatePickSelection(mouseEvent->scenePos()); - m_firstSelection = true; - } - - m_pivot = calcBoundingRect(m_selectedItems).center(); - } - - m_editedSelectedItems = false; - m_offset = QPointF(0, 0); - m_angle = 0; - m_scaleFactor = QPointF(1.0, 1.0); - - if (m_mode == WorldEditorScene::SelectMode) - m_selectionArea.setTopLeft(mouseEvent->scenePos()); -} - -void WorldEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - if (QApplication::mouseButtons() == Qt::LeftButton) - { - m_selectionArea.setBottomRight(mouseEvent->scenePos()); - switch (m_mode) - { - case WorldEditorScene::SelectMode: - break; - case WorldEditorScene::MoveMode: - updateWorldItemsMove(mouseEvent); - break; - case WorldEditorScene::RotateMode: - updateWorldItemsRotate(mouseEvent); - break; - case WorldEditorScene::ScaleMode: - updateWorldItemsScale(mouseEvent); - break; - case WorldEditorScene::TurnMode: - updateWorldItemsTurn(mouseEvent); - break; - case WorldEditorScene::RadiusMode: - updateWorldItemsRadius(mouseEvent); - break; - }; - - if (isEnabledEditPoints()) - { - if ((editMode() != WorldEditorScene::SelectMode) && (!m_selectedPoints.isEmpty())) - m_editedSelectedItems = true; - else - m_editedSelectedItems = false; - } - else - { - if ((editMode() != WorldEditorScene::SelectMode) && (!m_selectedItems.isEmpty())) - m_editedSelectedItems = true; - else - m_editedSelectedItems = false; - } - // Update render (drawing selection area when enabled multiple selection mode) - update(); - } - - LandscapeEditor::LandscapeSceneBase::mouseMoveEvent(mouseEvent); -} - -void WorldEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) -{ - if (mouseEvent->button() == Qt::MidButton) - return; - - if (mouseEvent->button() == Qt::LeftButton) - { - checkUndo(); - - // Update selection - if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0)) - { - QList listItems; - - // Clear selection - updateSelectedPointItems(false); - m_selectedPoints.clear(); - - // Return list of selected items - if (m_selectionArea.left() < m_selectionArea.right()) - listItems = items(m_selectionArea, Qt::IntersectsItemShape, Qt::AscendingOrder); - else - listItems = items(m_selectionArea, Qt::ContainsItemShape, Qt::AscendingOrder); - - if (isEnabledEditPoints()) - { - Q_FOREACH(QGraphicsItem *item, listItems) - { - if (qgraphicsitem_cast(item) == 0) - continue; - m_selectedPoints.push_back(item); - } - updateSelectedPointItems(true); - } - else - { - Q_FOREACH(QGraphicsItem *item, listItems) - { - if (qgraphicsitem_cast(item) == 0) - continue; - m_selectedItems.push_back(item); - } - Q_EMIT updateSelectedItems(m_selectedItems); - updateSelectedWorldItems(true); - } - m_selectionArea = QRectF(); - update(); - } - else - { - if ((!m_editedSelectedItems) && (!m_firstSelection)) - { - if (isEnabledEditPoints()) - updatePickSelectionPoints(mouseEvent->scenePos()); - else - updatePickSelection(mouseEvent->scenePos()); - } - else - m_firstSelection = false; - } - - if (isEnabledEditPoints()) - checkUndoPointsMode(); - } - m_selectionArea = QRectF(); - LandscapeEditor::LandscapeSceneBase::mouseReleaseEvent(mouseEvent); -} - -QRectF WorldEditorScene::calcBoundingRect(const QList &listItems) -{ - QRectF rect; - Q_FOREACH(QGraphicsItem *item, listItems) - { - QRectF itemRect = item->boundingRect(); - rect = rect.united(itemRect.translated(item->scenePos())); - } - return rect; -} - -QPainterPath WorldEditorScene::calcBoundingShape(const QList &listItems) -{ - QPainterPath painterPath; - Q_FOREACH(QGraphicsItem *item, listItems) - { - QPainterPath itemPath = item->shape(); - painterPath = painterPath.united(itemPath.translated(item->scenePos())); - } - return painterPath; -} - -void WorldEditorScene::updateSelectedWorldItems(bool value) -{ - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - updateSelectedWorldItem(item, value); - } - update(); -} - -void WorldEditorScene::updateSelectedWorldItem(QGraphicsItem *item, bool value) -{ - AbstractWorldItem *worldItem = qgraphicsitem_cast(item); - if (worldItem != 0) - worldItem->setActived(value); -} - -void WorldEditorScene::updateSelectedPointItems(bool value) -{ - Q_FOREACH(QGraphicsItem *item, m_selectedPoints) - { - updateSelectedPointItem(item, value); - } - update(); -} - -void WorldEditorScene::updateSelectedPointItem(QGraphicsItem *item, bool value) -{ - WorldItemSubPoint *worldItem = qgraphicsitem_cast(item); - if (worldItem != 0) - worldItem->setActived(value); -} - -void WorldEditorScene::updatePickSelection(const QPointF &point) -{ - updateSelectedWorldItems(false); - m_selectedItems.clear(); - - QList listItems = items(point, Qt::ContainsItemShape, - Qt::AscendingOrder); - - QList worldItemsItems; - - Q_FOREACH(QGraphicsItem *item, listItems) - { - AbstractWorldItem *worldItem = qgraphicsitem_cast(item); - if (worldItem != 0) - worldItemsItems.push_back(worldItem); - } - - if (!worldItemsItems.isEmpty()) - { - // Next primitives - m_lastPickedPrimitive++; - m_lastPickedPrimitive %= worldItemsItems.size(); - - m_selectedItems.push_back(worldItemsItems.at(m_lastPickedPrimitive)); - updateSelectedWorldItems(true); - } - - Q_EMIT updateSelectedItems(m_selectedItems); -} - -void WorldEditorScene::updatePickSelectionPoints(const QPointF &point) -{ - updateSelectedPointItems(false); - m_selectedPoints.clear(); - - QList listItems = items(point, Qt::IntersectsItemBoundingRect, - Qt::AscendingOrder); - - QList subPointsItems; - - Q_FOREACH(QGraphicsItem *item, listItems) - { - WorldItemSubPoint *subPointItem = qgraphicsitem_cast(item); - if (subPointItem != 0) - { - if (subPointItem->subPointType() == WorldItemSubPoint::EdgeType) - subPointsItems.push_back(subPointItem); - } - } - - if (!subPointsItems.isEmpty()) - { - // Next primitives - m_lastPickedPrimitive++; - m_lastPickedPrimitive %= subPointsItems.size(); - - m_selectedPoints.push_back(subPointsItems.at(m_lastPickedPrimitive)); - updateSelectedPointItems(true); - } -} - -void WorldEditorScene::checkUndo() -{ - if (m_editedSelectedItems && (!isEnabledEditPoints())) - { - switch (m_mode) - { - case WorldEditorScene::SelectMode: - break; - case WorldEditorScene::MoveMode: - m_undoStack->push(new MoveWorldItemsCommand(m_selectedItems, m_offset, this, m_model)); - break; - case WorldEditorScene::RotateMode: - m_undoStack->push(new RotateWorldItemsCommand(m_selectedItems, m_angle, m_pivot, this, m_model)); - break; - case WorldEditorScene::ScaleMode: - m_undoStack->push(new ScaleWorldItemsCommand(m_selectedItems, m_scaleFactor, m_pivot, this, m_model)); - break; - case WorldEditorScene::TurnMode: - m_undoStack->push(new TurnWorldItemsCommand(m_selectedItems, m_angle, this, m_model)); - break; - case WorldEditorScene::RadiusMode: - break; - }; - } -} - -void WorldEditorScene::checkUndoPointsMode() -{ - if (m_pointsMode) - { - QList items; - QList polygons; - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - AbstractWorldItem *worldItem = qgraphicsitem_cast(item); - if (worldItem->isShapeChanged()) - { - items.push_back(item); - polygons.push_back(m_polygons.at(m_selectedItems.indexOf(item))); - worldItem->setShapeChanged(false); - } - } - if (!items.isEmpty()) - { - m_undoStack->push(new ShapeWorldItemsCommand(items, polygons, this, m_model)); - m_polygons.clear(); - } - } -} - -void WorldEditorScene::updateWorldItemsMove(QGraphicsSceneMouseEvent *mouseEvent) -{ - QPointF offset = mouseEvent->scenePos() - mouseEvent->lastScenePos(); - m_offset += offset; - if (m_pointsMode) - Q_FOREACH(QGraphicsItem *item, m_selectedPoints) - { - item->moveBy(offset.x(), offset.y()); - } - else - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - item->moveBy(offset.x(), offset.y()); - } -} - -void WorldEditorScene::updateWorldItemsScale(QGraphicsSceneMouseEvent *mouseEvent) -{ - QPointF offset(mouseEvent->scenePos() - mouseEvent->lastScenePos()); - - qreal scaleRatio = 5000; - - // Calculate scale factor - if (offset.x() > 0) - offset.setX(1.0 + (offset.x() / scaleRatio)); - else - offset.setX(1.0 / (1.0 + (-offset.x() / scaleRatio))); - - if (offset.y() < 0) - offset.setY(1.0 - (offset.y() / scaleRatio)); - else - offset.setY(1.0 / (1.0 + (offset.y() / scaleRatio))); - - m_scaleFactor.setX(offset.x() * m_scaleFactor.x()); - m_scaleFactor.setY(offset.y() * m_scaleFactor.y()); - - if (m_pointsMode) - Q_FOREACH(QGraphicsItem *item, m_selectedPoints) - { - qgraphicsitem_cast(item)->scaleOn(m_pivot, offset); - } - else - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - qgraphicsitem_cast(item)->scaleOn(m_pivot, offset); - } -} - -void WorldEditorScene::updateWorldItemsRotate(QGraphicsSceneMouseEvent *mouseEvent) -{ - // Caluculate angle between two line - QLineF firstLine(m_pivot, mouseEvent->lastScenePos()); - QLineF secondLine(m_pivot, mouseEvent->scenePos()); - qreal angle = secondLine.angleTo(firstLine); - m_angle += angle; - - if (m_pointsMode) - Q_FOREACH(QGraphicsItem *item, m_selectedPoints) - { - qgraphicsitem_cast(item)->rotateOn(m_pivot, angle); - } - else - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - qgraphicsitem_cast(item)->rotateOn(m_pivot, angle); - } -} - -void WorldEditorScene::updateWorldItemsTurn(QGraphicsSceneMouseEvent *mouseEvent) -{ - // Caluculate angle between two line - QLineF firstLine(m_pivot, mouseEvent->lastScenePos()); - QLineF secondLine(m_pivot, mouseEvent->scenePos()); - qreal angle = secondLine.angleTo(firstLine); - m_angle += angle; - - Q_FOREACH(QGraphicsItem *item, m_selectedItems) - { - qgraphicsitem_cast(item)->turnOn(angle); - } -} - -void WorldEditorScene::updateWorldItemsRadius(QGraphicsSceneMouseEvent *mouseEvent) -{ -} - -} /* namespace WorldEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_scene.h" +#include "world_editor_scene_item.h" +#include "world_editor_actions.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include + +namespace WorldEditor +{ + +WorldEditorScene::WorldEditorScene(int sizeCell, PrimitivesTreeModel *model, QUndoStack *undoStack, QObject *parent) + : LandscapeEditor::LandscapeSceneBase(sizeCell, parent), + m_editedSelectedItems(false), + m_lastPickedPrimitive(0), + m_mode(SelectMode), + m_pointsMode(false), + m_undoStack(undoStack), + m_model(model) +{ + setItemIndexMethod(NoIndex); + + // TODO: get params from settings + setSceneRect(QRectF(-20 * 160, -20 * 160, 256 * 160, 256 * 160)); + + m_greenPen.setColor(QColor(50, 255, 155)); + m_greenPen.setWidth(0); + m_greenBrush.setColor(QColor(50, 255, 155, 80)); + m_greenBrush.setStyle(Qt::SolidPattern); + + m_purplePen.setColor(QColor(100, 0, 255)); + m_purplePen.setWidth(0); + m_purpleBrush.setColor(QColor(100, 0, 255, 80)); + m_purpleBrush.setStyle(Qt::SolidPattern); +} + +WorldEditorScene::~WorldEditorScene() +{ +} + +AbstractWorldItem *WorldEditorScene::addWorldItemPoint(const QPointF &point, const qreal angle, + const qreal radius, bool showArrow) +{ + WorldItemPoint *item = new WorldItemPoint(point, angle, radius, showArrow); + addItem(item); + return item; +} + +AbstractWorldItem *WorldEditorScene::addWorldItemPath(const QPolygonF &polyline, bool showArrow) +{ + WorldItemPath *item = new WorldItemPath(polyline); + addItem(item); + return item; +} + +AbstractWorldItem *WorldEditorScene::addWorldItemZone(const QPolygonF &polygon) +{ + WorldItemZone *item = new WorldItemZone(polygon); + addItem(item); + return item; +} + +void WorldEditorScene::removeWorldItem(QGraphicsItem *item) +{ + updateSelectedWorldItems(true); + m_selectedItems.clear(); + m_editedSelectedItems = false; + m_firstSelection = false; + delete item; +} + +void WorldEditorScene::setModeEdit(WorldEditorScene::ModeEdit mode) +{ + if (mode == WorldEditorScene::SelectMode) + m_editedSelectedItems = false; + + m_mode = mode; +} + +WorldEditorScene::ModeEdit WorldEditorScene::editMode() const +{ + return m_mode; +} + +bool WorldEditorScene::isEnabledEditPoints() const +{ + return m_pointsMode; +} + +void WorldEditorScene::setEnabledEditPoints(bool enabled) +{ + if (m_pointsMode == enabled) + return; + + m_pointsMode = enabled; + + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + AbstractWorldItem *worldItem = qgraphicsitem_cast(item); + if (worldItem != 0) + worldItem->setEnabledSubPoints(enabled); + } + + m_selectedPoints.clear(); +} + +void WorldEditorScene::updateSelection(const QList &selected, const QList &deselected) +{ + // Deselect and remove from list graphics items. + Q_FOREACH(QGraphicsItem *item, deselected) + { + // Item is selected? + int i = m_selectedItems.indexOf(item); + if (i != -1) + { + updateSelectedWorldItem(item, false); + m_selectedItems.takeAt(i); + } + } + + // Select and add from list graphics items. + Q_FOREACH(QGraphicsItem *item, selected) + { + // Item is selected? + int i = m_selectedItems.indexOf(item); + if (i == -1) + { + updateSelectedWorldItem(item, true); + m_selectedItems.push_back(item); + } + } + + update(); + m_firstSelection = true; +} + +void WorldEditorScene::drawForeground(QPainter *painter, const QRectF &rect) +{ + QGraphicsScene::drawForeground(painter, rect); + + if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0)) + { + // Draw selection area + if (m_selectionArea.left() < m_selectionArea.right()) + { + painter->setPen(m_greenPen); + painter->setBrush(m_greenBrush); + } + else + { + painter->setPen(m_purplePen); + painter->setBrush(m_purpleBrush); + } + painter->drawRect(m_selectionArea); + } +} + +void WorldEditorScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + m_firstPick = mouseEvent->scenePos(); + + if (isEnabledEditPoints()) + { + m_polygons = polygonsFromItems(m_selectedItems); + + if (mouseEvent->button() == Qt::LeftButton) + { + // Create new sub-points + // Call method mousePressEvent for sub-point located under mouse + LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); + + if ((!m_editedSelectedItems && m_selectedPoints.isEmpty()) || + (!calcBoundingRect(m_selectedPoints).contains(mouseEvent->scenePos()))) + { + updatePickSelectionPoints(mouseEvent->scenePos()); + m_firstSelection = true; + } + m_pivot = calcBoundingRect(m_selectedPoints).center(); + } + else if (mouseEvent->button() == Qt::RightButton) + { + updateSelectedPointItems(false); + m_selectedPoints.clear(); + + // Delete sub-points if it located under mouse + // Call method mousePressEvent for sub-point located under mouse + LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); + } + } + else + { + LandscapeEditor::LandscapeSceneBase::mousePressEvent(mouseEvent); + + if (mouseEvent->button() != Qt::LeftButton) + return; + + if ((!m_editedSelectedItems && m_selectedItems.isEmpty()) || + (!calcBoundingRect(m_selectedItems).contains(mouseEvent->scenePos()))) + { + updatePickSelection(mouseEvent->scenePos()); + m_firstSelection = true; + } + + m_pivot = calcBoundingRect(m_selectedItems).center(); + } + + m_editedSelectedItems = false; + m_offset = QPointF(0, 0); + m_angle = 0; + m_scaleFactor = QPointF(1.0, 1.0); + + if (m_mode == WorldEditorScene::SelectMode) + m_selectionArea.setTopLeft(mouseEvent->scenePos()); +} + +void WorldEditorScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + if (QApplication::mouseButtons() == Qt::LeftButton) + { + m_selectionArea.setBottomRight(mouseEvent->scenePos()); + switch (m_mode) + { + case WorldEditorScene::SelectMode: + break; + case WorldEditorScene::MoveMode: + updateWorldItemsMove(mouseEvent); + break; + case WorldEditorScene::RotateMode: + updateWorldItemsRotate(mouseEvent); + break; + case WorldEditorScene::ScaleMode: + updateWorldItemsScale(mouseEvent); + break; + case WorldEditorScene::TurnMode: + updateWorldItemsTurn(mouseEvent); + break; + case WorldEditorScene::RadiusMode: + updateWorldItemsRadius(mouseEvent); + break; + }; + + if (isEnabledEditPoints()) + { + if ((editMode() != WorldEditorScene::SelectMode) && (!m_selectedPoints.isEmpty())) + m_editedSelectedItems = true; + else + m_editedSelectedItems = false; + } + else + { + if ((editMode() != WorldEditorScene::SelectMode) && (!m_selectedItems.isEmpty())) + m_editedSelectedItems = true; + else + m_editedSelectedItems = false; + } + // Update render (drawing selection area when enabled multiple selection mode) + update(); + } + + LandscapeEditor::LandscapeSceneBase::mouseMoveEvent(mouseEvent); +} + +void WorldEditorScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) +{ + if (mouseEvent->button() == Qt::MidButton) + return; + + if (mouseEvent->button() == Qt::LeftButton) + { + checkUndo(); + + // Update selection + if ((m_selectionArea.left() != 0) && (m_selectionArea.right() != 0)) + { + QList listItems; + + // Clear selection + updateSelectedPointItems(false); + m_selectedPoints.clear(); + + // Return list of selected items + if (m_selectionArea.left() < m_selectionArea.right()) + listItems = items(m_selectionArea, Qt::IntersectsItemShape, Qt::AscendingOrder); + else + listItems = items(m_selectionArea, Qt::ContainsItemShape, Qt::AscendingOrder); + + if (isEnabledEditPoints()) + { + Q_FOREACH(QGraphicsItem *item, listItems) + { + if (qgraphicsitem_cast(item) == 0) + continue; + m_selectedPoints.push_back(item); + } + updateSelectedPointItems(true); + } + else + { + Q_FOREACH(QGraphicsItem *item, listItems) + { + if (qgraphicsitem_cast(item) == 0) + continue; + m_selectedItems.push_back(item); + } + Q_EMIT updateSelectedItems(m_selectedItems); + updateSelectedWorldItems(true); + } + m_selectionArea = QRectF(); + update(); + } + else + { + if ((!m_editedSelectedItems) && (!m_firstSelection)) + { + if (isEnabledEditPoints()) + updatePickSelectionPoints(mouseEvent->scenePos()); + else + updatePickSelection(mouseEvent->scenePos()); + } + else + m_firstSelection = false; + } + + if (isEnabledEditPoints()) + checkUndoPointsMode(); + } + m_selectionArea = QRectF(); + LandscapeEditor::LandscapeSceneBase::mouseReleaseEvent(mouseEvent); +} + +QRectF WorldEditorScene::calcBoundingRect(const QList &listItems) +{ + QRectF rect; + Q_FOREACH(QGraphicsItem *item, listItems) + { + QRectF itemRect = item->boundingRect(); + rect = rect.united(itemRect.translated(item->scenePos())); + } + return rect; +} + +QPainterPath WorldEditorScene::calcBoundingShape(const QList &listItems) +{ + QPainterPath painterPath; + Q_FOREACH(QGraphicsItem *item, listItems) + { + QPainterPath itemPath = item->shape(); + painterPath = painterPath.united(itemPath.translated(item->scenePos())); + } + return painterPath; +} + +void WorldEditorScene::updateSelectedWorldItems(bool value) +{ + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + updateSelectedWorldItem(item, value); + } + update(); +} + +void WorldEditorScene::updateSelectedWorldItem(QGraphicsItem *item, bool value) +{ + AbstractWorldItem *worldItem = qgraphicsitem_cast(item); + if (worldItem != 0) + worldItem->setActived(value); +} + +void WorldEditorScene::updateSelectedPointItems(bool value) +{ + Q_FOREACH(QGraphicsItem *item, m_selectedPoints) + { + updateSelectedPointItem(item, value); + } + update(); +} + +void WorldEditorScene::updateSelectedPointItem(QGraphicsItem *item, bool value) +{ + WorldItemSubPoint *worldItem = qgraphicsitem_cast(item); + if (worldItem != 0) + worldItem->setActived(value); +} + +void WorldEditorScene::updatePickSelection(const QPointF &point) +{ + updateSelectedWorldItems(false); + m_selectedItems.clear(); + + QList listItems = items(point, Qt::ContainsItemShape, + Qt::AscendingOrder); + + QList worldItemsItems; + + Q_FOREACH(QGraphicsItem *item, listItems) + { + AbstractWorldItem *worldItem = qgraphicsitem_cast(item); + if (worldItem != 0) + worldItemsItems.push_back(worldItem); + } + + if (!worldItemsItems.isEmpty()) + { + // Next primitives + m_lastPickedPrimitive++; + m_lastPickedPrimitive %= worldItemsItems.size(); + + m_selectedItems.push_back(worldItemsItems.at(m_lastPickedPrimitive)); + updateSelectedWorldItems(true); + } + + Q_EMIT updateSelectedItems(m_selectedItems); +} + +void WorldEditorScene::updatePickSelectionPoints(const QPointF &point) +{ + updateSelectedPointItems(false); + m_selectedPoints.clear(); + + QList listItems = items(point, Qt::IntersectsItemBoundingRect, + Qt::AscendingOrder); + + QList subPointsItems; + + Q_FOREACH(QGraphicsItem *item, listItems) + { + WorldItemSubPoint *subPointItem = qgraphicsitem_cast(item); + if (subPointItem != 0) + { + if (subPointItem->subPointType() == WorldItemSubPoint::EdgeType) + subPointsItems.push_back(subPointItem); + } + } + + if (!subPointsItems.isEmpty()) + { + // Next primitives + m_lastPickedPrimitive++; + m_lastPickedPrimitive %= subPointsItems.size(); + + m_selectedPoints.push_back(subPointsItems.at(m_lastPickedPrimitive)); + updateSelectedPointItems(true); + } +} + +void WorldEditorScene::checkUndo() +{ + if (m_editedSelectedItems && (!isEnabledEditPoints())) + { + switch (m_mode) + { + case WorldEditorScene::SelectMode: + break; + case WorldEditorScene::MoveMode: + m_undoStack->push(new MoveWorldItemsCommand(m_selectedItems, m_offset, this, m_model)); + break; + case WorldEditorScene::RotateMode: + m_undoStack->push(new RotateWorldItemsCommand(m_selectedItems, m_angle, m_pivot, this, m_model)); + break; + case WorldEditorScene::ScaleMode: + m_undoStack->push(new ScaleWorldItemsCommand(m_selectedItems, m_scaleFactor, m_pivot, this, m_model)); + break; + case WorldEditorScene::TurnMode: + m_undoStack->push(new TurnWorldItemsCommand(m_selectedItems, m_angle, this, m_model)); + break; + case WorldEditorScene::RadiusMode: + break; + }; + } +} + +void WorldEditorScene::checkUndoPointsMode() +{ + if (m_pointsMode) + { + QList items; + QList polygons; + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + AbstractWorldItem *worldItem = qgraphicsitem_cast(item); + if (worldItem->isShapeChanged()) + { + items.push_back(item); + polygons.push_back(m_polygons.at(m_selectedItems.indexOf(item))); + worldItem->setShapeChanged(false); + } + } + if (!items.isEmpty()) + { + m_undoStack->push(new ShapeWorldItemsCommand(items, polygons, this, m_model)); + m_polygons.clear(); + } + } +} + +void WorldEditorScene::updateWorldItemsMove(QGraphicsSceneMouseEvent *mouseEvent) +{ + QPointF offset = mouseEvent->scenePos() - mouseEvent->lastScenePos(); + m_offset += offset; + if (m_pointsMode) + Q_FOREACH(QGraphicsItem *item, m_selectedPoints) + { + item->moveBy(offset.x(), offset.y()); + } + else + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + item->moveBy(offset.x(), offset.y()); + } +} + +void WorldEditorScene::updateWorldItemsScale(QGraphicsSceneMouseEvent *mouseEvent) +{ + QPointF offset(mouseEvent->scenePos() - mouseEvent->lastScenePos()); + + qreal scaleRatio = 5000; + + // Calculate scale factor + if (offset.x() > 0) + offset.setX(1.0 + (offset.x() / scaleRatio)); + else + offset.setX(1.0 / (1.0 + (-offset.x() / scaleRatio))); + + if (offset.y() < 0) + offset.setY(1.0 - (offset.y() / scaleRatio)); + else + offset.setY(1.0 / (1.0 + (offset.y() / scaleRatio))); + + m_scaleFactor.setX(offset.x() * m_scaleFactor.x()); + m_scaleFactor.setY(offset.y() * m_scaleFactor.y()); + + if (m_pointsMode) + Q_FOREACH(QGraphicsItem *item, m_selectedPoints) + { + qgraphicsitem_cast(item)->scaleOn(m_pivot, offset); + } + else + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + qgraphicsitem_cast(item)->scaleOn(m_pivot, offset); + } +} + +void WorldEditorScene::updateWorldItemsRotate(QGraphicsSceneMouseEvent *mouseEvent) +{ + // Caluculate angle between two line + QLineF firstLine(m_pivot, mouseEvent->lastScenePos()); + QLineF secondLine(m_pivot, mouseEvent->scenePos()); + qreal angle = secondLine.angleTo(firstLine); + m_angle += angle; + + if (m_pointsMode) + Q_FOREACH(QGraphicsItem *item, m_selectedPoints) + { + qgraphicsitem_cast(item)->rotateOn(m_pivot, angle); + } + else + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + qgraphicsitem_cast(item)->rotateOn(m_pivot, angle); + } +} + +void WorldEditorScene::updateWorldItemsTurn(QGraphicsSceneMouseEvent *mouseEvent) +{ + // Caluculate angle between two line + QLineF firstLine(m_pivot, mouseEvent->lastScenePos()); + QLineF secondLine(m_pivot, mouseEvent->scenePos()); + qreal angle = secondLine.angleTo(firstLine); + m_angle += angle; + + Q_FOREACH(QGraphicsItem *item, m_selectedItems) + { + qgraphicsitem_cast(item)->turnOn(angle); + } +} + +void WorldEditorScene::updateWorldItemsRadius(QGraphicsSceneMouseEvent *mouseEvent) +{ +} + +} /* namespace WorldEditor */ diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp index 1375c40ab..544feae89 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_scene_item.cpp @@ -1,741 +1,741 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_scene_item.h" - -// NeL includes -#include - -// Qt includes -#include -#include -#include -#include -#include -#include - -namespace WorldEditor -{ - -static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen) -{ - // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 - // if we pass a value of 0.0 to QPainterPathStroker::setWidth() - const qreal penWidthZero = qreal(0.00000001); - - if (path == QPainterPath()) - return path; - QPainterPathStroker ps; - ps.setCapStyle(pen.capStyle()); - if (pen.widthF() <= 0.0) - ps.setWidth(penWidthZero); - else - ps.setWidth(pen.widthF()); - ps.setJoinStyle(pen.joinStyle()); - ps.setMiterLimit(pen.miterLimit()); - QPainterPath p = ps.createStroke(path); - p.addPath(path); - return p; -} - -AbstractWorldItem::AbstractWorldItem(QGraphicsItem *parent) - : QGraphicsItem(parent), - m_active(false), - m_shapeChanged(false) -{ -} - -AbstractWorldItem::~AbstractWorldItem() -{ -} - -int AbstractWorldItem::type() const -{ - return Type; -} - -void AbstractWorldItem::setActived(bool actived) -{ - m_active = actived; -} - -bool AbstractWorldItem::isActived() const -{ - return m_active; -} - -void AbstractWorldItem::setShapeChanged(bool value) -{ - m_shapeChanged = value; -} - -bool AbstractWorldItem::isShapeChanged() const -{ - return m_shapeChanged; -} - -WorldItemPoint::WorldItemPoint(const QPointF &point, const qreal angle, const qreal radius, - bool showArrow, QGraphicsItem *parent) - : AbstractWorldItem(parent), - m_angle(angle), - m_radius(radius), - m_showArrow(showArrow) -{ - setZValue(WORLD_POINT_LAYER); - - //setFlag(ItemIgnoresTransformations); - - setPos(point); - - m_rect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); - - m_pen.setColor(QColor(255, 100, 10)); - //m_pen.setWidth(0); - - m_selectedPen.setColor(Qt::white); - //m_selectedPen.setWidth(0); - - m_brush.setColor(QColor(255, 100, 10)); - m_brush.setStyle(Qt::SolidPattern); - - m_selectedBrush.setColor(Qt::white); - m_selectedBrush.setStyle(Qt::SolidPattern); - - createCircle(); - - // Create arrow - if (showArrow) - { - m_arrow.push_back(QLine(0, 0, SIZE_ARROW, 0)); - m_arrow.push_back(QLine(SIZE_ARROW - 2, -2, SIZE_ARROW, 0)); - m_arrow.push_back(QLine(SIZE_ARROW - 2, 2, SIZE_ARROW, 0)); - } - - updateBoundingRect(); -} - -WorldItemPoint::~WorldItemPoint() -{ -} - -qreal WorldItemPoint::angle() const -{ - return m_angle; -} - -void WorldItemPoint::rotateOn(const QPointF &pivot, const qreal deltaAngle) -{ - prepareGeometryChange(); - - QPolygonF rotatedPolygon(m_rect); - - rotatedPolygon.translate(pos() - pivot); - - QTransform trans; - trans = trans.rotate(deltaAngle); - rotatedPolygon = trans.map(rotatedPolygon); - rotatedPolygon.translate(pivot); - - setPos(rotatedPolygon.boundingRect().center()); -} - -void WorldItemPoint::scaleOn(const QPointF &pivot, const QPointF &factor) -{ - prepareGeometryChange(); - - QPolygonF scaledPolygon(m_rect); - - scaledPolygon.translate(pos() - pivot); - - QTransform trans; - trans = trans.scale(factor.x(), factor.y()); - scaledPolygon = trans.map(scaledPolygon); - scaledPolygon.translate(pivot); - - setPos(scaledPolygon.boundingRect().center()); -} - -void WorldItemPoint::turnOn(const qreal angle) -{ - m_angle += angle; - m_angle -= floor(m_angle / 360) * 360; - update(); -} - -void WorldItemPoint::radiusOn(const qreal radius) -{ - if (m_radius == 0) - return; - - // TODO: implement -} - -void WorldItemPoint::setColor(const QColor &color) -{ - m_pen.setColor(color); - m_brush.setColor(color); -} - -void WorldItemPoint::setPolygon(const QPolygonF &polygon) -{ -} - -QPolygonF WorldItemPoint::polygon() const -{ - QPolygonF polygon; - polygon << QPointF(0, 0); - return polygon; -} - -void WorldItemPoint::createCircle() -{ - if (m_radius != 0) - { - // Create circle - int segmentCount = 20; - QPointF circlePoint(m_radius, 0); - m_circle << circlePoint; - for (int i = 1; i < segmentCount + 1; ++i) - { - qreal angle = i * (2 * NLMISC::Pi / segmentCount); - circlePoint.setX(cos(angle) * m_radius); - circlePoint.setY(sin(angle) * m_radius); - m_circle << circlePoint; - } - } -} - -void WorldItemPoint::updateBoundingRect() -{ - m_boundingRect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); - QRectF circleBoundingRect; - circleBoundingRect.setCoords(-m_radius, -m_radius, m_radius, m_radius); - m_boundingRect = m_boundingRect.united(circleBoundingRect); -} - -QPainterPath WorldItemPoint::shape() const -{ - QPainterPath path; - - path.addRect(m_boundingRect); - return qt_graphicsItem_shapeFromPath(path, m_pen); -} - -QRectF WorldItemPoint::boundingRect() const -{ - return m_boundingRect; -} - -void WorldItemPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) -{ - painter->setPen(m_pen); - - // Draw circle - // Draws artefacts with using opengl painter - // painter->drawEllipse(-m_radius / 2, -m_radius / 2, m_radius, m_radius); - painter->drawPolygon(m_circle); - - painter->rotate(m_angle); - - // Draw arrow - painter->drawLines(m_arrow); - - painter->setPen(Qt::NoPen); - if (isActived()) - painter->setBrush(m_selectedBrush); - else - painter->setBrush(m_brush); - - // Draw point - painter->drawRect(m_rect); -} - -BaseWorldItemPolyline::BaseWorldItemPolyline(const QPolygonF &polygon, QGraphicsItem *parent) - : AbstractWorldItem(parent), - m_polyline(polygon), - m_pointEdit(false) -{ - //setFlag(ItemIsSelectable); - QPointF center = m_polyline.boundingRect().center(); - m_polyline.translate(-center); - setPos(center); -} - -BaseWorldItemPolyline::~BaseWorldItemPolyline() -{ -} - -void BaseWorldItemPolyline::rotateOn(const QPointF &pivot, const qreal deltaAngle) -{ - prepareGeometryChange(); - - QPolygonF rotatedPolygon(m_polyline); - rotatedPolygon.translate(pos() - pivot); - - QTransform trans; - trans = trans.rotate(deltaAngle); - m_polyline = trans.map(rotatedPolygon); - - m_polyline.translate(pivot - pos()); -} - -void BaseWorldItemPolyline::scaleOn(const QPointF &pivot, const QPointF &factor) -{ - prepareGeometryChange(); - - QPolygonF scaledPolygon(m_polyline); - scaledPolygon.translate(pos() - pivot); - - QTransform trans; - trans = trans.scale(factor.x(), factor.y()); - m_polyline = trans.map(scaledPolygon); - - m_polyline.translate(pivot - pos()); -} - -void BaseWorldItemPolyline::setEnabledSubPoints(bool enabled) -{ - m_pointEdit = enabled; - if (m_pointEdit) - createSubPoints(); - else - removeSubPoints(); - - setShapeChanged(false); -} - -void BaseWorldItemPolyline::moveSubPoint(WorldItemSubPoint *subPoint) -{ - prepareGeometryChange(); - - QPolygonF polygon; - - // Update polygon - Q_FOREACH(WorldItemSubPoint *node, m_listItems) - { - polygon << node->pos(); - } - - // Update middle points - for (int i = 0; i < m_listLines.size(); ++i) - m_listLines.at(i).itemPoint->setPos((m_listLines.at(i).lineItem.first->pos() + m_listLines.at(i).lineItem.second->pos()) / 2); - - m_polyline = polygon; - setShapeChanged(true); - update(); -} - -void BaseWorldItemPolyline::addSubPoint(WorldItemSubPoint *subPoint) -{ - prepareGeometryChange(); - - for (int i = 0; i < m_listLines.size(); ++i) - { - if (subPoint == m_listLines.at(i).itemPoint) - { - LineStruct oldLineItem = m_listLines[i]; - - // Create the first middle sub-point - WorldItemSubPoint *firstItem = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); - firstItem->setPos((oldLineItem.lineItem.first->pos() + subPoint->pos()) / 2); - - // Create the second middle sub-point - WorldItemSubPoint *secondItem = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); - secondItem->setPos((oldLineItem.lineItem.second->pos() + subPoint->pos()) / 2); - - // Add first line in the list - LineStruct firstNewLineItem; - firstNewLineItem.itemPoint = firstItem; - firstNewLineItem.lineItem = LineItem(oldLineItem.lineItem.first, subPoint); - m_listLines.push_back(firstNewLineItem); - - // Add second line in the list - LineStruct secondNewLineItem; - secondNewLineItem.itemPoint = secondItem; - secondNewLineItem.lineItem = LineItem(subPoint, oldLineItem.lineItem.second); - m_listLines.push_back(secondNewLineItem); - - m_listLines.removeAt(i); - - int pos = m_listItems.indexOf(oldLineItem.lineItem.second); - m_listItems.insert(pos, subPoint); - subPoint->setFlag(ItemSendsScenePositionChanges); - - break; - } - } - setShapeChanged(true); -} - -bool BaseWorldItemPolyline::removeSubPoint(WorldItemSubPoint *subPoint) -{ - prepareGeometryChange(); - - int pos = m_listItems.indexOf(subPoint); - m_listItems.takeAt(pos); - LineStruct newLineItem; - newLineItem.itemPoint = subPoint; - - // Delete first line - for (int i = 0; i < m_listLines.size(); ++i) - { - if (subPoint == m_listLines.at(i).lineItem.first) - { - // Saving second point for new line - newLineItem.lineItem.second = m_listLines.at(i).lineItem.second; - delete m_listLines.at(i).itemPoint; - m_listLines.removeAt(i); - break; - } - } - - // Delete second line - for (int i = 0; i < m_listLines.size(); ++i) - { - if (subPoint == m_listLines.at(i).lineItem.second) - { - // Saving first point for new line - newLineItem.lineItem.first = m_listLines.at(i).lineItem.first; - delete m_listLines.at(i).itemPoint; - m_listLines.removeAt(i); - break; - } - } - subPoint->setPos((newLineItem.lineItem.first->pos() + newLineItem.lineItem.second->pos()) / 2); - m_listLines.push_back(newLineItem); - subPoint->setFlag(ItemSendsScenePositionChanges, false); - setShapeChanged(true); - return true; -} - -void BaseWorldItemPolyline::setPolygon(const QPolygonF &polygon) -{ - prepareGeometryChange(); - m_polyline = polygon; - update(); -} - -QPolygonF BaseWorldItemPolyline::polygon() const -{ - return m_polyline; -} - -QRectF BaseWorldItemPolyline::boundingRect() const -{ - return m_polyline.boundingRect(); -} - -void BaseWorldItemPolyline::createSubPoints() -{ - WorldItemSubPoint *firstPoint; - firstPoint = new WorldItemSubPoint(WorldItemSubPoint::EdgeType, this); - firstPoint->setPos(m_polyline.front()); - firstPoint->setFlag(ItemSendsScenePositionChanges); - m_listItems.push_back(firstPoint); - - for (int i = 1; i < m_polyline.count(); ++i) - { - WorldItemSubPoint *secondPoint = new WorldItemSubPoint(WorldItemSubPoint::EdgeType, this); - secondPoint->setPos(m_polyline.at(i)); - secondPoint->setFlag(ItemSendsScenePositionChanges); - - WorldItemSubPoint *middlePoint = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); - middlePoint->setPos((firstPoint->pos() + secondPoint->pos()) / 2); - - LineStruct newLineItem; - newLineItem.itemPoint = middlePoint; - newLineItem.lineItem = LineItem(firstPoint, secondPoint); - m_listLines.push_back(newLineItem); - - firstPoint = secondPoint; - m_listItems.push_back(firstPoint); - } -} - -void BaseWorldItemPolyline::removeSubPoints() -{ - for (int i = 0; i < m_listLines.count(); ++i) - delete m_listLines.at(i).itemPoint; - - for (int i = 0; i < m_listItems.count(); ++i) - delete m_listItems.at(i); - - m_listItems.clear(); - m_listLines.clear(); -} - -WorldItemPath::WorldItemPath(const QPolygonF &polygon, QGraphicsItem *parent) - : BaseWorldItemPolyline(polygon, parent) -{ - setZValue(WORLD_PATH_LAYER); - - m_pen.setColor(Qt::black); - m_pen.setWidth(3); - m_pen.setJoinStyle(Qt::MiterJoin); - - m_selectedPen.setColor(Qt::white); - m_selectedPen.setWidth(3); - m_selectedPen.setJoinStyle(Qt::MiterJoin); -} - -WorldItemPath::~WorldItemPath() -{ -} - -void WorldItemPath::setColor(const QColor &color) -{ - m_pen.setColor(color); -} - -bool WorldItemPath::removeSubPoint(WorldItemSubPoint *subPoint) -{ - int pos = m_listItems.indexOf(subPoint); - - // First and second points can not be removed - if ((pos == 0) || (pos == m_listItems.size() - 1)) - return false; - - return BaseWorldItemPolyline::removeSubPoint(subPoint); -} - -QPainterPath WorldItemPath::shape() const -{ - QPainterPath path; - - path.moveTo(m_polyline.first()); - for (int i = 1; i < m_polyline.count(); ++i) - path.lineTo(m_polyline.at(i)); - - return qt_graphicsItem_shapeFromPath(path, m_pen); -} - -void WorldItemPath::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) -{ - if (isActived()) - painter->setPen(m_selectedPen); - else - painter->setPen(m_pen); - - painter->drawPolyline(m_polyline); -} - - -WorldItemZone::WorldItemZone(const QPolygonF &polygon, QGraphicsItem *parent) - : BaseWorldItemPolyline(polygon, parent) -{ - setZValue(WORLD_ZONE_LAYER); - - m_pen.setColor(QColor(20, 100, 255)); - m_pen.setWidth(0); - m_selectedPen.setColor(Qt::white); - m_selectedPen.setWidth(0); - m_brush.setColor(QColor(20, 100, 255, TRANSPARENCY)); - m_brush.setStyle(Qt::SolidPattern); - m_selectedBrush.setColor(QColor(255, 255, 255, 100)); - m_selectedBrush.setStyle(Qt::SolidPattern); -} - -WorldItemZone::~WorldItemZone() -{ -} - -void WorldItemZone::setColor(const QColor &color) -{ - m_pen.setColor(color); - QColor brushColor(color); - brushColor.setAlpha(TRANSPARENCY); - m_brush.setColor(brushColor); -} - -bool WorldItemZone::removeSubPoint(WorldItemSubPoint *subPoint) -{ - if (m_listItems.size() < 4) - return false; - - return BaseWorldItemPolyline::removeSubPoint(subPoint); -} - -QPainterPath WorldItemZone::shape() const -{ - QPainterPath path; - path.addPolygon(m_polyline); - return qt_graphicsItem_shapeFromPath(path, m_pen); -} - -void WorldItemZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) -{ - if (isActived()) - { - painter->setPen(m_selectedPen); - painter->setBrush(m_selectedBrush); - } - else - { - painter->setPen(m_pen); - painter->setBrush(m_brush); - } - - painter->drawPolygon(m_polyline); -} - -void WorldItemZone::createSubPoints() -{ - BaseWorldItemPolyline::createSubPoints(); - - LineStruct endLineItem; - endLineItem.itemPoint = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); - endLineItem.itemPoint->setPos((m_listItems.first()->pos() + m_listItems.last()->pos()) / 2); - endLineItem.lineItem = LineItem(m_listItems.last(), m_listItems.first()); - m_listLines.push_back(endLineItem); -} - -//******************************************* - -WorldItemSubPoint::WorldItemSubPoint(SubPointType pointType, AbstractWorldItem *parent) - : QGraphicsObject(parent), - m_type(pointType), - m_active(false), - m_parent(parent) -{ - setZValue(WORLD_POINT_LAYER); - - m_brush.setColor(QColor(20, 100, 255)); - m_brush.setStyle(Qt::SolidPattern); - - m_brushMiddle.setColor(QColor(255, 25, 100)); - m_brushMiddle.setStyle(Qt::SolidPattern); - - m_selectedBrush.setColor(QColor(255, 255, 255, 100)); - m_selectedBrush.setStyle(Qt::SolidPattern); - - m_rect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); - updateBoundingRect(); - - //setFlag(ItemIgnoresTransformations); - //setFlag(ItemSendsScenePositionChanges); -} - -WorldItemSubPoint::~WorldItemSubPoint() -{ -} - -void WorldItemSubPoint::setSubPointType(SubPointType nodeType) -{ - m_type = nodeType; - setFlag(ItemSendsScenePositionChanges); -} - -WorldItemSubPoint::SubPointType WorldItemSubPoint::subPointType() const -{ - return m_type; -} - -void WorldItemSubPoint::rotateOn(const QPointF &pivot, const qreal deltaAngle) -{ - prepareGeometryChange(); - - QPolygonF rotatedPolygon(m_rect); - rotatedPolygon.translate(scenePos() - pivot); - - QTransform trans; - trans = trans.rotate(deltaAngle); - rotatedPolygon = trans.map(rotatedPolygon); - rotatedPolygon.translate(pivot); - - setPos(m_parent->mapFromParent(rotatedPolygon.boundingRect().center())); -} - -void WorldItemSubPoint::scaleOn(const QPointF &pivot, const QPointF &factor) -{ - prepareGeometryChange(); - - QPolygonF scaledPolygon(m_rect); - scaledPolygon.translate(scenePos() - pivot); - - QTransform trans; - trans = trans.scale(factor.x(), factor.y()); - scaledPolygon = trans.map(scaledPolygon); - scaledPolygon.translate(pivot); - - setPos(m_parent->mapFromParent(scaledPolygon.boundingRect().center())); -} - -QRectF WorldItemSubPoint::boundingRect() const -{ - return m_boundingRect; -} - -void WorldItemSubPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) -{ - painter->setPen(Qt::NoPen); - if (m_type == WorldItemSubPoint::EdgeType) - { - if (isActived()) - painter->setBrush(m_selectedBrush); - else - painter->setBrush(m_brush); - } - else - painter->setBrush(m_brushMiddle); - - // Draw point - painter->drawRect(m_rect); -} - -int WorldItemSubPoint::type() const -{ - return Type; -} - -void WorldItemSubPoint::setActived(bool actived) -{ - m_active = actived; -} - -bool WorldItemSubPoint::isActived() const -{ - return m_active; -} - -QVariant WorldItemSubPoint::itemChange(GraphicsItemChange change, const QVariant &value) -{ - if (change == ItemPositionHasChanged) - m_parent->moveSubPoint(this); - return QGraphicsItem::itemChange(change, value); -} - -void WorldItemSubPoint::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - if ((m_type == MiddleType) && (event->button() == Qt::LeftButton)) - { - m_parent->addSubPoint(this); - setSubPointType(EdgeType); - } - else if ((m_type == EdgeType) && (event->button() == Qt::RightButton)) - { - if (m_parent->removeSubPoint(this)) - setSubPointType(MiddleType); - } - update(); -} - -void WorldItemSubPoint::updateBoundingRect() -{ - m_boundingRect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); -} - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_scene_item.h" + +// NeL includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include + +namespace WorldEditor +{ + +static QPainterPath qt_graphicsItem_shapeFromPath(const QPainterPath &path, const QPen &pen) +{ + // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0 + // if we pass a value of 0.0 to QPainterPathStroker::setWidth() + const qreal penWidthZero = qreal(0.00000001); + + if (path == QPainterPath()) + return path; + QPainterPathStroker ps; + ps.setCapStyle(pen.capStyle()); + if (pen.widthF() <= 0.0) + ps.setWidth(penWidthZero); + else + ps.setWidth(pen.widthF()); + ps.setJoinStyle(pen.joinStyle()); + ps.setMiterLimit(pen.miterLimit()); + QPainterPath p = ps.createStroke(path); + p.addPath(path); + return p; +} + +AbstractWorldItem::AbstractWorldItem(QGraphicsItem *parent) + : QGraphicsItem(parent), + m_active(false), + m_shapeChanged(false) +{ +} + +AbstractWorldItem::~AbstractWorldItem() +{ +} + +int AbstractWorldItem::type() const +{ + return Type; +} + +void AbstractWorldItem::setActived(bool actived) +{ + m_active = actived; +} + +bool AbstractWorldItem::isActived() const +{ + return m_active; +} + +void AbstractWorldItem::setShapeChanged(bool value) +{ + m_shapeChanged = value; +} + +bool AbstractWorldItem::isShapeChanged() const +{ + return m_shapeChanged; +} + +WorldItemPoint::WorldItemPoint(const QPointF &point, const qreal angle, const qreal radius, + bool showArrow, QGraphicsItem *parent) + : AbstractWorldItem(parent), + m_angle(angle), + m_radius(radius), + m_showArrow(showArrow) +{ + setZValue(WORLD_POINT_LAYER); + + //setFlag(ItemIgnoresTransformations); + + setPos(point); + + m_rect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); + + m_pen.setColor(QColor(255, 100, 10)); + //m_pen.setWidth(0); + + m_selectedPen.setColor(Qt::white); + //m_selectedPen.setWidth(0); + + m_brush.setColor(QColor(255, 100, 10)); + m_brush.setStyle(Qt::SolidPattern); + + m_selectedBrush.setColor(Qt::white); + m_selectedBrush.setStyle(Qt::SolidPattern); + + createCircle(); + + // Create arrow + if (showArrow) + { + m_arrow.push_back(QLine(0, 0, SIZE_ARROW, 0)); + m_arrow.push_back(QLine(SIZE_ARROW - 2, -2, SIZE_ARROW, 0)); + m_arrow.push_back(QLine(SIZE_ARROW - 2, 2, SIZE_ARROW, 0)); + } + + updateBoundingRect(); +} + +WorldItemPoint::~WorldItemPoint() +{ +} + +qreal WorldItemPoint::angle() const +{ + return m_angle; +} + +void WorldItemPoint::rotateOn(const QPointF &pivot, const qreal deltaAngle) +{ + prepareGeometryChange(); + + QPolygonF rotatedPolygon(m_rect); + + rotatedPolygon.translate(pos() - pivot); + + QTransform trans; + trans = trans.rotate(deltaAngle); + rotatedPolygon = trans.map(rotatedPolygon); + rotatedPolygon.translate(pivot); + + setPos(rotatedPolygon.boundingRect().center()); +} + +void WorldItemPoint::scaleOn(const QPointF &pivot, const QPointF &factor) +{ + prepareGeometryChange(); + + QPolygonF scaledPolygon(m_rect); + + scaledPolygon.translate(pos() - pivot); + + QTransform trans; + trans = trans.scale(factor.x(), factor.y()); + scaledPolygon = trans.map(scaledPolygon); + scaledPolygon.translate(pivot); + + setPos(scaledPolygon.boundingRect().center()); +} + +void WorldItemPoint::turnOn(const qreal angle) +{ + m_angle += angle; + m_angle -= floor(m_angle / 360) * 360; + update(); +} + +void WorldItemPoint::radiusOn(const qreal radius) +{ + if (m_radius == 0) + return; + + // TODO: implement +} + +void WorldItemPoint::setColor(const QColor &color) +{ + m_pen.setColor(color); + m_brush.setColor(color); +} + +void WorldItemPoint::setPolygon(const QPolygonF &polygon) +{ +} + +QPolygonF WorldItemPoint::polygon() const +{ + QPolygonF polygon; + polygon << QPointF(0, 0); + return polygon; +} + +void WorldItemPoint::createCircle() +{ + if (m_radius != 0) + { + // Create circle + int segmentCount = 20; + QPointF circlePoint(m_radius, 0); + m_circle << circlePoint; + for (int i = 1; i < segmentCount + 1; ++i) + { + qreal angle = i * (2 * NLMISC::Pi / segmentCount); + circlePoint.setX(cos(angle) * m_radius); + circlePoint.setY(sin(angle) * m_radius); + m_circle << circlePoint; + } + } +} + +void WorldItemPoint::updateBoundingRect() +{ + m_boundingRect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); + QRectF circleBoundingRect; + circleBoundingRect.setCoords(-m_radius, -m_radius, m_radius, m_radius); + m_boundingRect = m_boundingRect.united(circleBoundingRect); +} + +QPainterPath WorldItemPoint::shape() const +{ + QPainterPath path; + + path.addRect(m_boundingRect); + return qt_graphicsItem_shapeFromPath(path, m_pen); +} + +QRectF WorldItemPoint::boundingRect() const +{ + return m_boundingRect; +} + +void WorldItemPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + painter->setPen(m_pen); + + // Draw circle + // Draws artefacts with using opengl painter + // painter->drawEllipse(-m_radius / 2, -m_radius / 2, m_radius, m_radius); + painter->drawPolygon(m_circle); + + painter->rotate(m_angle); + + // Draw arrow + painter->drawLines(m_arrow); + + painter->setPen(Qt::NoPen); + if (isActived()) + painter->setBrush(m_selectedBrush); + else + painter->setBrush(m_brush); + + // Draw point + painter->drawRect(m_rect); +} + +BaseWorldItemPolyline::BaseWorldItemPolyline(const QPolygonF &polygon, QGraphicsItem *parent) + : AbstractWorldItem(parent), + m_polyline(polygon), + m_pointEdit(false) +{ + //setFlag(ItemIsSelectable); + QPointF center = m_polyline.boundingRect().center(); + m_polyline.translate(-center); + setPos(center); +} + +BaseWorldItemPolyline::~BaseWorldItemPolyline() +{ +} + +void BaseWorldItemPolyline::rotateOn(const QPointF &pivot, const qreal deltaAngle) +{ + prepareGeometryChange(); + + QPolygonF rotatedPolygon(m_polyline); + rotatedPolygon.translate(pos() - pivot); + + QTransform trans; + trans = trans.rotate(deltaAngle); + m_polyline = trans.map(rotatedPolygon); + + m_polyline.translate(pivot - pos()); +} + +void BaseWorldItemPolyline::scaleOn(const QPointF &pivot, const QPointF &factor) +{ + prepareGeometryChange(); + + QPolygonF scaledPolygon(m_polyline); + scaledPolygon.translate(pos() - pivot); + + QTransform trans; + trans = trans.scale(factor.x(), factor.y()); + m_polyline = trans.map(scaledPolygon); + + m_polyline.translate(pivot - pos()); +} + +void BaseWorldItemPolyline::setEnabledSubPoints(bool enabled) +{ + m_pointEdit = enabled; + if (m_pointEdit) + createSubPoints(); + else + removeSubPoints(); + + setShapeChanged(false); +} + +void BaseWorldItemPolyline::moveSubPoint(WorldItemSubPoint *subPoint) +{ + prepareGeometryChange(); + + QPolygonF polygon; + + // Update polygon + Q_FOREACH(WorldItemSubPoint *node, m_listItems) + { + polygon << node->pos(); + } + + // Update middle points + for (int i = 0; i < m_listLines.size(); ++i) + m_listLines.at(i).itemPoint->setPos((m_listLines.at(i).lineItem.first->pos() + m_listLines.at(i).lineItem.second->pos()) / 2); + + m_polyline = polygon; + setShapeChanged(true); + update(); +} + +void BaseWorldItemPolyline::addSubPoint(WorldItemSubPoint *subPoint) +{ + prepareGeometryChange(); + + for (int i = 0; i < m_listLines.size(); ++i) + { + if (subPoint == m_listLines.at(i).itemPoint) + { + LineStruct oldLineItem = m_listLines[i]; + + // Create the first middle sub-point + WorldItemSubPoint *firstItem = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); + firstItem->setPos((oldLineItem.lineItem.first->pos() + subPoint->pos()) / 2); + + // Create the second middle sub-point + WorldItemSubPoint *secondItem = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); + secondItem->setPos((oldLineItem.lineItem.second->pos() + subPoint->pos()) / 2); + + // Add first line in the list + LineStruct firstNewLineItem; + firstNewLineItem.itemPoint = firstItem; + firstNewLineItem.lineItem = LineItem(oldLineItem.lineItem.first, subPoint); + m_listLines.push_back(firstNewLineItem); + + // Add second line in the list + LineStruct secondNewLineItem; + secondNewLineItem.itemPoint = secondItem; + secondNewLineItem.lineItem = LineItem(subPoint, oldLineItem.lineItem.second); + m_listLines.push_back(secondNewLineItem); + + m_listLines.removeAt(i); + + int pos = m_listItems.indexOf(oldLineItem.lineItem.second); + m_listItems.insert(pos, subPoint); + subPoint->setFlag(ItemSendsScenePositionChanges); + + break; + } + } + setShapeChanged(true); +} + +bool BaseWorldItemPolyline::removeSubPoint(WorldItemSubPoint *subPoint) +{ + prepareGeometryChange(); + + int pos = m_listItems.indexOf(subPoint); + m_listItems.takeAt(pos); + LineStruct newLineItem; + newLineItem.itemPoint = subPoint; + + // Delete first line + for (int i = 0; i < m_listLines.size(); ++i) + { + if (subPoint == m_listLines.at(i).lineItem.first) + { + // Saving second point for new line + newLineItem.lineItem.second = m_listLines.at(i).lineItem.second; + delete m_listLines.at(i).itemPoint; + m_listLines.removeAt(i); + break; + } + } + + // Delete second line + for (int i = 0; i < m_listLines.size(); ++i) + { + if (subPoint == m_listLines.at(i).lineItem.second) + { + // Saving first point for new line + newLineItem.lineItem.first = m_listLines.at(i).lineItem.first; + delete m_listLines.at(i).itemPoint; + m_listLines.removeAt(i); + break; + } + } + subPoint->setPos((newLineItem.lineItem.first->pos() + newLineItem.lineItem.second->pos()) / 2); + m_listLines.push_back(newLineItem); + subPoint->setFlag(ItemSendsScenePositionChanges, false); + setShapeChanged(true); + return true; +} + +void BaseWorldItemPolyline::setPolygon(const QPolygonF &polygon) +{ + prepareGeometryChange(); + m_polyline = polygon; + update(); +} + +QPolygonF BaseWorldItemPolyline::polygon() const +{ + return m_polyline; +} + +QRectF BaseWorldItemPolyline::boundingRect() const +{ + return m_polyline.boundingRect(); +} + +void BaseWorldItemPolyline::createSubPoints() +{ + WorldItemSubPoint *firstPoint; + firstPoint = new WorldItemSubPoint(WorldItemSubPoint::EdgeType, this); + firstPoint->setPos(m_polyline.front()); + firstPoint->setFlag(ItemSendsScenePositionChanges); + m_listItems.push_back(firstPoint); + + for (int i = 1; i < m_polyline.count(); ++i) + { + WorldItemSubPoint *secondPoint = new WorldItemSubPoint(WorldItemSubPoint::EdgeType, this); + secondPoint->setPos(m_polyline.at(i)); + secondPoint->setFlag(ItemSendsScenePositionChanges); + + WorldItemSubPoint *middlePoint = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); + middlePoint->setPos((firstPoint->pos() + secondPoint->pos()) / 2); + + LineStruct newLineItem; + newLineItem.itemPoint = middlePoint; + newLineItem.lineItem = LineItem(firstPoint, secondPoint); + m_listLines.push_back(newLineItem); + + firstPoint = secondPoint; + m_listItems.push_back(firstPoint); + } +} + +void BaseWorldItemPolyline::removeSubPoints() +{ + for (int i = 0; i < m_listLines.count(); ++i) + delete m_listLines.at(i).itemPoint; + + for (int i = 0; i < m_listItems.count(); ++i) + delete m_listItems.at(i); + + m_listItems.clear(); + m_listLines.clear(); +} + +WorldItemPath::WorldItemPath(const QPolygonF &polygon, QGraphicsItem *parent) + : BaseWorldItemPolyline(polygon, parent) +{ + setZValue(WORLD_PATH_LAYER); + + m_pen.setColor(Qt::black); + m_pen.setWidth(3); + m_pen.setJoinStyle(Qt::MiterJoin); + + m_selectedPen.setColor(Qt::white); + m_selectedPen.setWidth(3); + m_selectedPen.setJoinStyle(Qt::MiterJoin); +} + +WorldItemPath::~WorldItemPath() +{ +} + +void WorldItemPath::setColor(const QColor &color) +{ + m_pen.setColor(color); +} + +bool WorldItemPath::removeSubPoint(WorldItemSubPoint *subPoint) +{ + int pos = m_listItems.indexOf(subPoint); + + // First and second points can not be removed + if ((pos == 0) || (pos == m_listItems.size() - 1)) + return false; + + return BaseWorldItemPolyline::removeSubPoint(subPoint); +} + +QPainterPath WorldItemPath::shape() const +{ + QPainterPath path; + + path.moveTo(m_polyline.first()); + for (int i = 1; i < m_polyline.count(); ++i) + path.lineTo(m_polyline.at(i)); + + return qt_graphicsItem_shapeFromPath(path, m_pen); +} + +void WorldItemPath::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + if (isActived()) + painter->setPen(m_selectedPen); + else + painter->setPen(m_pen); + + painter->drawPolyline(m_polyline); +} + + +WorldItemZone::WorldItemZone(const QPolygonF &polygon, QGraphicsItem *parent) + : BaseWorldItemPolyline(polygon, parent) +{ + setZValue(WORLD_ZONE_LAYER); + + m_pen.setColor(QColor(20, 100, 255)); + m_pen.setWidth(0); + m_selectedPen.setColor(Qt::white); + m_selectedPen.setWidth(0); + m_brush.setColor(QColor(20, 100, 255, TRANSPARENCY)); + m_brush.setStyle(Qt::SolidPattern); + m_selectedBrush.setColor(QColor(255, 255, 255, 100)); + m_selectedBrush.setStyle(Qt::SolidPattern); +} + +WorldItemZone::~WorldItemZone() +{ +} + +void WorldItemZone::setColor(const QColor &color) +{ + m_pen.setColor(color); + QColor brushColor(color); + brushColor.setAlpha(TRANSPARENCY); + m_brush.setColor(brushColor); +} + +bool WorldItemZone::removeSubPoint(WorldItemSubPoint *subPoint) +{ + if (m_listItems.size() < 4) + return false; + + return BaseWorldItemPolyline::removeSubPoint(subPoint); +} + +QPainterPath WorldItemZone::shape() const +{ + QPainterPath path; + path.addPolygon(m_polyline); + return qt_graphicsItem_shapeFromPath(path, m_pen); +} + +void WorldItemZone::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + if (isActived()) + { + painter->setPen(m_selectedPen); + painter->setBrush(m_selectedBrush); + } + else + { + painter->setPen(m_pen); + painter->setBrush(m_brush); + } + + painter->drawPolygon(m_polyline); +} + +void WorldItemZone::createSubPoints() +{ + BaseWorldItemPolyline::createSubPoints(); + + LineStruct endLineItem; + endLineItem.itemPoint = new WorldItemSubPoint(WorldItemSubPoint::MiddleType, this); + endLineItem.itemPoint->setPos((m_listItems.first()->pos() + m_listItems.last()->pos()) / 2); + endLineItem.lineItem = LineItem(m_listItems.last(), m_listItems.first()); + m_listLines.push_back(endLineItem); +} + +//******************************************* + +WorldItemSubPoint::WorldItemSubPoint(SubPointType pointType, AbstractWorldItem *parent) + : QGraphicsObject(parent), + m_type(pointType), + m_active(false), + m_parent(parent) +{ + setZValue(WORLD_POINT_LAYER); + + m_brush.setColor(QColor(20, 100, 255)); + m_brush.setStyle(Qt::SolidPattern); + + m_brushMiddle.setColor(QColor(255, 25, 100)); + m_brushMiddle.setStyle(Qt::SolidPattern); + + m_selectedBrush.setColor(QColor(255, 255, 255, 100)); + m_selectedBrush.setStyle(Qt::SolidPattern); + + m_rect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); + updateBoundingRect(); + + //setFlag(ItemIgnoresTransformations); + //setFlag(ItemSendsScenePositionChanges); +} + +WorldItemSubPoint::~WorldItemSubPoint() +{ +} + +void WorldItemSubPoint::setSubPointType(SubPointType nodeType) +{ + m_type = nodeType; + setFlag(ItemSendsScenePositionChanges); +} + +WorldItemSubPoint::SubPointType WorldItemSubPoint::subPointType() const +{ + return m_type; +} + +void WorldItemSubPoint::rotateOn(const QPointF &pivot, const qreal deltaAngle) +{ + prepareGeometryChange(); + + QPolygonF rotatedPolygon(m_rect); + rotatedPolygon.translate(scenePos() - pivot); + + QTransform trans; + trans = trans.rotate(deltaAngle); + rotatedPolygon = trans.map(rotatedPolygon); + rotatedPolygon.translate(pivot); + + setPos(m_parent->mapFromParent(rotatedPolygon.boundingRect().center())); +} + +void WorldItemSubPoint::scaleOn(const QPointF &pivot, const QPointF &factor) +{ + prepareGeometryChange(); + + QPolygonF scaledPolygon(m_rect); + scaledPolygon.translate(scenePos() - pivot); + + QTransform trans; + trans = trans.scale(factor.x(), factor.y()); + scaledPolygon = trans.map(scaledPolygon); + scaledPolygon.translate(pivot); + + setPos(m_parent->mapFromParent(scaledPolygon.boundingRect().center())); +} + +QRectF WorldItemSubPoint::boundingRect() const +{ + return m_boundingRect; +} + +void WorldItemSubPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + painter->setPen(Qt::NoPen); + if (m_type == WorldItemSubPoint::EdgeType) + { + if (isActived()) + painter->setBrush(m_selectedBrush); + else + painter->setBrush(m_brush); + } + else + painter->setBrush(m_brushMiddle); + + // Draw point + painter->drawRect(m_rect); +} + +int WorldItemSubPoint::type() const +{ + return Type; +} + +void WorldItemSubPoint::setActived(bool actived) +{ + m_active = actived; +} + +bool WorldItemSubPoint::isActived() const +{ + return m_active; +} + +QVariant WorldItemSubPoint::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionHasChanged) + m_parent->moveSubPoint(this); + return QGraphicsItem::itemChange(change, value); +} + +void WorldItemSubPoint::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if ((m_type == MiddleType) && (event->button() == Qt::LeftButton)) + { + m_parent->addSubPoint(this); + setSubPointType(EdgeType); + } + else if ((m_type == EdgeType) && (event->button() == Qt::RightButton)) + { + if (m_parent->removeSubPoint(this)) + setSubPointType(MiddleType); + } + update(); +} + +void WorldItemSubPoint::updateBoundingRect() +{ + m_boundingRect.setCoords(-SIZE_POINT, -SIZE_POINT, SIZE_POINT, SIZE_POINT); +} + } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp index f3b3e6551..bb8ef2a00 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_settings_page.cpp @@ -1,71 +1,71 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_settings_page.h" -#include "world_editor_constants.h" - -// Qt includes -#include - -// NeL includes - -namespace WorldEditor -{ - -WorldEditorSettingsPage::WorldEditorSettingsPage(QObject *parent) - : IOptionsPage(parent), - m_currentPage(NULL) -{ -} - -QString WorldEditorSettingsPage::id() const -{ - return QLatin1String(Constants::WORLD_EDITOR_PLUGIN); -} - -QString WorldEditorSettingsPage::trName() const -{ - return tr("General"); -} - -QString WorldEditorSettingsPage::category() const -{ - return QLatin1String(Constants::WORLD_EDITOR_PLUGIN); -} - -QString WorldEditorSettingsPage::trCategory() const -{ - return tr("World Editor"); -} - -QIcon WorldEditorSettingsPage::categoryIcon() const -{ - return QIcon(); -} - -QWidget *WorldEditorSettingsPage::createPage(QWidget *parent) -{ - m_currentPage = new QWidget(parent); - m_ui.setupUi(m_currentPage); - return m_currentPage; -} - -void WorldEditorSettingsPage::apply() -{ -} - +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_settings_page.h" +#include "world_editor_constants.h" + +// Qt includes +#include + +// NeL includes + +namespace WorldEditor +{ + +WorldEditorSettingsPage::WorldEditorSettingsPage(QObject *parent) + : IOptionsPage(parent), + m_currentPage(NULL) +{ +} + +QString WorldEditorSettingsPage::id() const +{ + return QLatin1String(Constants::WORLD_EDITOR_PLUGIN); +} + +QString WorldEditorSettingsPage::trName() const +{ + return tr("General"); +} + +QString WorldEditorSettingsPage::category() const +{ + return QLatin1String(Constants::WORLD_EDITOR_PLUGIN); +} + +QString WorldEditorSettingsPage::trCategory() const +{ + return tr("World Editor"); +} + +QIcon WorldEditorSettingsPage::categoryIcon() const +{ + return QIcon(); +} + +QWidget *WorldEditorSettingsPage::createPage(QWidget *parent) +{ + m_currentPage = new QWidget(parent); + m_ui.setupUi(m_currentPage); + return m_currentPage; +} + +void WorldEditorSettingsPage::apply() +{ +} + } /* namespace WorldEditor */ \ No newline at end of file diff --git a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp index 382b356c0..7bdff078b 100644 --- a/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp +++ b/code/nel/tools/3d/object_viewer_qt/src/plugins/world_editor/world_editor_window.cpp @@ -1,422 +1,422 @@ -// Object Viewer Qt - MMORPG Framework -// Copyright (C) 2011 Dzmitry Kamiahin -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Project includes -#include "world_editor_window.h" -#include "world_editor_constants.h" -#include "primitives_model.h" -#include "world_editor_scene.h" -#include "world_editor_misc.h" -#include "world_editor_actions.h" -#include "world_editor_scene_item.h" -#include "project_settings_dialog.h" - -// Core -#include "../core/icore.h" -#include "../core/menu_manager.h" -#include "../core/core_constants.h" - -// Lanscape Editor plugin -#include "../landscape_editor/builder_zone_base.h" - -// NeL includes - -// Qt includes -#include -#include -#include -#include -#include - -namespace WorldEditor -{ - -WorldEditorWindow::WorldEditorWindow(QWidget *parent) - : QMainWindow(parent), - m_primitivesModel(0), - m_undoStack(0), - m_oglWidget(0) -{ - m_ui.setupUi(this); - m_undoStack = new QUndoStack(this); - - m_primitivesModel = new PrimitivesTreeModel(this); - - m_worldEditorScene = new WorldEditorScene(Utils::ligoConfig()->CellSize, m_primitivesModel, m_undoStack, this); - m_zoneBuilderBase = new LandscapeEditor::ZoneBuilderBase(m_worldEditorScene); - - m_worldEditorScene->setZoneBuilder(m_zoneBuilderBase); - m_ui.graphicsView->setScene(m_worldEditorScene); - m_ui.graphicsView->setVisibleText(false); - - m_ui.treePrimitivesView->setModel(m_primitivesModel); - m_ui.treePrimitivesView->setUndoStack(m_undoStack); - m_ui.treePrimitivesView->setZoneBuilder(m_zoneBuilderBase); - m_ui.treePrimitivesView->setWorldScene(m_worldEditorScene); - - QActionGroup *sceneModeGroup = new QActionGroup(this); - sceneModeGroup->addAction(m_ui.selectAction); - sceneModeGroup->addAction(m_ui.moveAction); - sceneModeGroup->addAction(m_ui.rotateAction); - sceneModeGroup->addAction(m_ui.scaleAction); - sceneModeGroup->addAction(m_ui.turnAction); - m_ui.selectAction->setChecked(true); - - m_ui.newWorldEditAction->setIcon(QIcon(Core::Constants::ICON_NEW)); - m_ui.saveWorldEditAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); - - createMenus(); - createToolBars(); - readSettings(); - - QSignalMapper *m_modeMapper = new QSignalMapper(this); - connect(m_ui.selectAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); - m_modeMapper->setMapping(m_ui.selectAction, 0); - connect(m_ui.moveAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); - m_modeMapper->setMapping(m_ui.moveAction, 1); - connect(m_ui.rotateAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); - m_modeMapper->setMapping(m_ui.rotateAction, 2); - connect(m_ui.scaleAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); - m_modeMapper->setMapping(m_ui.scaleAction, 3); - connect(m_ui.turnAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); - m_modeMapper->setMapping(m_ui.turnAction, 4); - - connect(m_modeMapper, SIGNAL(mapped(int)), this, SLOT(setMode(int))); - connect(m_ui.pointsAction, SIGNAL(triggered(bool)), m_worldEditorScene, SLOT(setEnabledEditPoints(bool))); - - connect(m_ui.settingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings())); - connect(m_ui.newWorldEditAction, SIGNAL(triggered()), this, SLOT(newWorldEditFile())); - connect(m_ui.saveWorldEditAction, SIGNAL(triggered()), this, SLOT(saveWorldEditFile())); - connect(m_ui.visibleGridAction, SIGNAL(toggled(bool)), m_ui.graphicsView, SLOT(setVisibleGrid(bool))); - - connect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(updateSelection(QItemSelection, QItemSelection))); - - connect(m_worldEditorScene, SIGNAL(updateSelectedItems(QList)), - this, SLOT(selectedItemsInScene(QList))); - - m_statusBarTimer = new QTimer(this); - connect(m_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); - - m_statusInfo = new QLabel(this); - m_statusInfo->hide(); - Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(m_statusInfo); -} - -WorldEditorWindow::~WorldEditorWindow() -{ - writeSettings(); - - delete m_zoneBuilderBase; -} - -QUndoStack *WorldEditorWindow::undoStack() const -{ - return m_undoStack; -} - -void WorldEditorWindow::maybeSave() -{ - QMessageBox *messageBox = new QMessageBox(tr("World Editor"), - tr("The data has been modified.\n" - "Do you want to save your changes?"), - QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::Default, - QMessageBox::No, - QMessageBox::Cancel | QMessageBox::Escape, - this, Qt::Sheet); - - messageBox->setButtonText(QMessageBox::Yes, - tr("Save")); - - messageBox->setButtonText(QMessageBox::No, tr("Don't Save")); - - messageBox->show(); -} - -void WorldEditorWindow::open() -{ - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open NeL World Edit file"), m_lastDir, - tr("All NeL World Editor file (*.worldedit)")); - - setCursor(Qt::WaitCursor); - if (!fileName.isEmpty()) - { - m_lastDir = QFileInfo(fileName).absolutePath(); - loadWorldEditFile(fileName); - } - setCursor(Qt::ArrowCursor); -} - -void WorldEditorWindow::loadWorldEditFile(const QString &fileName) -{ - if (m_primitivesModel->isWorldEditNodeLoaded()) - return; - - Utils::WorldEditList worldEditList; - if (!Utils::loadWorldEditFile(fileName.toStdString(), worldEditList)) - { - // TODO: add the message box - return; - } - - m_undoStack->beginMacro(tr("Load %1").arg(fileName)); - - checkCurrentWorld(); - - m_undoStack->push(new CreateWorldCommand(fileName, m_primitivesModel)); - for (size_t i = 0; i < worldEditList.size(); ++i) - { - switch (worldEditList[i].first) - { - case Utils::DataDirectoryType: - m_zoneBuilderBase->init(QString(worldEditList[i].second.c_str()), true); - break; - case Utils::ContextType: - break; - case Utils::LandscapeType: - m_undoStack->push(new LoadLandscapeCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel, m_zoneBuilderBase)); - break; - case Utils::PrimitiveType: - m_undoStack->push(new LoadRootPrimitiveCommand(QString(worldEditList[i].second.c_str()), - m_worldEditorScene, m_primitivesModel, m_ui.treePrimitivesView)); - break; - }; - } - m_undoStack->endMacro(); -} - -void WorldEditorWindow::checkCurrentWorld() -{ -} - -void WorldEditorWindow::newWorldEditFile() -{ - checkCurrentWorld(); - m_undoStack->push(new CreateWorldCommand("NewWorldEdit", m_primitivesModel)); -} - -void WorldEditorWindow::saveWorldEditFile() -{ -} - -void WorldEditorWindow::openProjectSettings() -{ - ProjectSettingsDialog *dialog = new ProjectSettingsDialog(m_zoneBuilderBase->dataPath(), this); - dialog->show(); - int ok = dialog->exec(); - if (ok == QDialog::Accepted) - { - m_zoneBuilderBase->init(dialog->dataPath(), true); - } - delete dialog; -} - -void WorldEditorWindow::setMode(int value) -{ - switch (value) - { - case 0: - m_worldEditorScene->setModeEdit(WorldEditorScene::SelectMode); - break; - case 1: - m_worldEditorScene->setModeEdit(WorldEditorScene::MoveMode); - break; - case 2: - m_worldEditorScene->setModeEdit(WorldEditorScene::RotateMode); - break; - case 3: - m_worldEditorScene->setModeEdit(WorldEditorScene::ScaleMode); - break; - case 4: - m_worldEditorScene->setModeEdit(WorldEditorScene::TurnMode); - break; - case 5: - m_worldEditorScene->setModeEdit(WorldEditorScene::RadiusMode); - break; - } -} - -void WorldEditorWindow::updateStatusBar() -{ - m_statusInfo->setText(m_worldEditorScene->zoneNameFromMousePos()); -} - -void WorldEditorWindow::updateSelection(const QItemSelection &selected, const QItemSelection &deselected) -{ - m_ui.pointsAction->setChecked(false); - m_worldEditorScene->setEnabledEditPoints(false); - - NodeList nodesSelected; - Q_FOREACH(QModelIndex modelIndex, selected.indexes()) - { - Node *node = static_cast(modelIndex.internalPointer()); - nodesSelected.push_back(node); - } - - NodeList nodesDeselected; - Q_FOREACH(QModelIndex modelIndex, deselected.indexes()) - { - Node *node = static_cast(modelIndex.internalPointer()); - nodesDeselected.push_back(node); - } - - // update property editor - if (nodesSelected.size() > 0) - { - // only single selection - m_ui.propertyEditWidget->updateSelection(nodesSelected.at(0)); - } - else - { - m_ui.propertyEditWidget->clearProperties(); - } - - QList itemSelected; - Q_FOREACH(Node *node, nodesSelected) - { - QGraphicsItem *item = getGraphicsItem(node); - if (item != 0) - itemSelected.push_back(item); - } - - QList itemDeselected; - Q_FOREACH(Node *node, nodesDeselected) - { - QGraphicsItem *item = getGraphicsItem(node); - if (item != 0) - itemDeselected.push_back(item); - } - - // Update world editor scene - m_worldEditorScene->updateSelection(itemSelected, itemDeselected); -} - -void WorldEditorWindow::selectedItemsInScene(const QList &selected) -{ - QItemSelectionModel *selectionModel = m_ui.treePrimitivesView->selectionModel(); - disconnect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(updateSelection(QItemSelection, QItemSelection))); - - selectionModel->clear(); - QItemSelection itemSelection; - Q_FOREACH(QGraphicsItem *item, selected) - { - QPersistentModelIndex *index = qvariant_cast(item->data(Constants::NODE_PERISTENT_INDEX)); - if (index->isValid()) - { - QModelIndex modelIndex = index->operator const QModelIndex &(); - QItemSelection mergeItemSelection(modelIndex, modelIndex); - itemSelection.merge(mergeItemSelection, QItemSelectionModel::Select); - } - QApplication::processEvents(); - } - - selectionModel->select(itemSelection, QItemSelectionModel::Select); - - // update property editor - if (!selected.isEmpty()) - { - // only single selection - Node *node = qvariant_cast(selected.at(0)->data(Constants::WORLD_EDITOR_NODE)); - m_ui.propertyEditWidget->updateSelection(node); - } - else - { - m_ui.propertyEditWidget->clearProperties(); - } - - connect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(updateSelection(QItemSelection, QItemSelection))); -} - -void WorldEditorWindow::showEvent(QShowEvent *showEvent) -{ - QMainWindow::showEvent(showEvent); - if (m_oglWidget != 0) - m_oglWidget->makeCurrent(); - m_statusInfo->show(); - m_statusBarTimer->start(100); -} - -void WorldEditorWindow::hideEvent(QHideEvent *hideEvent) -{ - QMainWindow::hideEvent(hideEvent); - m_statusInfo->hide(); - m_statusBarTimer->stop(); -} - -void WorldEditorWindow::createMenus() -{ - //Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); -} - -void WorldEditorWindow::createToolBars() -{ - Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); - //QAction *action = menuManager->action(Core::Constants::NEW); - //m_ui.fileToolBar->addAction(action); - - m_ui.fileToolBar->addAction(m_ui.newWorldEditAction); - QAction *action = menuManager->action(Core::Constants::OPEN); - m_ui.fileToolBar->addAction(action); - m_ui.fileToolBar->addAction(m_ui.saveWorldEditAction); - m_ui.fileToolBar->addSeparator(); - - action = menuManager->action(Core::Constants::UNDO); - if (action != 0) - m_ui.fileToolBar->addAction(action); - - action = menuManager->action(Core::Constants::REDO); - if (action != 0) - m_ui.fileToolBar->addAction(action); - - //action = menuManager->action(Core::Constants::SAVE); - //m_ui.fileToolBar->addAction(action); - //action = menuManager->action(Core::Constants::SAVE_AS); - //m_ui.fileToolBar->addAction(action); -} - -void WorldEditorWindow::readSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Constants::WORLD_EDITOR_SECTION); - restoreState(settings->value(Constants::WORLD_WINDOW_STATE).toByteArray()); - restoreGeometry(settings->value(Constants::WORLD_WINDOW_GEOMETRY).toByteArray()); - - // Use OpenGL graphics system instead raster graphics system - if (settings->value(Constants::WORLD_EDITOR_USE_OPENGL, true).toBool()) - { - m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer)); - //m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers)); - m_ui.graphicsView->setViewport(m_oglWidget); - } - - settings->endGroup(); -} - -void WorldEditorWindow::writeSettings() -{ - QSettings *settings = Core::ICore::instance()->settings(); - settings->beginGroup(Constants::WORLD_EDITOR_SECTION); - settings->setValue(Constants::WORLD_WINDOW_STATE, saveState()); - settings->setValue(Constants::WORLD_WINDOW_GEOMETRY, saveGeometry()); - settings->endGroup(); - settings->sync(); -} - -} /* namespace LandscapeEditor */ +// Object Viewer Qt - MMORPG Framework +// Copyright (C) 2011 Dzmitry Kamiahin +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Project includes +#include "world_editor_window.h" +#include "world_editor_constants.h" +#include "primitives_model.h" +#include "world_editor_scene.h" +#include "world_editor_misc.h" +#include "world_editor_actions.h" +#include "world_editor_scene_item.h" +#include "project_settings_dialog.h" + +// Core +#include "../core/icore.h" +#include "../core/menu_manager.h" +#include "../core/core_constants.h" + +// Lanscape Editor plugin +#include "../landscape_editor/builder_zone_base.h" + +// NeL includes + +// Qt includes +#include +#include +#include +#include +#include + +namespace WorldEditor +{ + +WorldEditorWindow::WorldEditorWindow(QWidget *parent) + : QMainWindow(parent), + m_primitivesModel(0), + m_undoStack(0), + m_oglWidget(0) +{ + m_ui.setupUi(this); + m_undoStack = new QUndoStack(this); + + m_primitivesModel = new PrimitivesTreeModel(this); + + m_worldEditorScene = new WorldEditorScene(Utils::ligoConfig()->CellSize, m_primitivesModel, m_undoStack, this); + m_zoneBuilderBase = new LandscapeEditor::ZoneBuilderBase(m_worldEditorScene); + + m_worldEditorScene->setZoneBuilder(m_zoneBuilderBase); + m_ui.graphicsView->setScene(m_worldEditorScene); + m_ui.graphicsView->setVisibleText(false); + + m_ui.treePrimitivesView->setModel(m_primitivesModel); + m_ui.treePrimitivesView->setUndoStack(m_undoStack); + m_ui.treePrimitivesView->setZoneBuilder(m_zoneBuilderBase); + m_ui.treePrimitivesView->setWorldScene(m_worldEditorScene); + + QActionGroup *sceneModeGroup = new QActionGroup(this); + sceneModeGroup->addAction(m_ui.selectAction); + sceneModeGroup->addAction(m_ui.moveAction); + sceneModeGroup->addAction(m_ui.rotateAction); + sceneModeGroup->addAction(m_ui.scaleAction); + sceneModeGroup->addAction(m_ui.turnAction); + m_ui.selectAction->setChecked(true); + + m_ui.newWorldEditAction->setIcon(QIcon(Core::Constants::ICON_NEW)); + m_ui.saveWorldEditAction->setIcon(QIcon(Core::Constants::ICON_SAVE)); + + createMenus(); + createToolBars(); + readSettings(); + + QSignalMapper *m_modeMapper = new QSignalMapper(this); + connect(m_ui.selectAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); + m_modeMapper->setMapping(m_ui.selectAction, 0); + connect(m_ui.moveAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); + m_modeMapper->setMapping(m_ui.moveAction, 1); + connect(m_ui.rotateAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); + m_modeMapper->setMapping(m_ui.rotateAction, 2); + connect(m_ui.scaleAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); + m_modeMapper->setMapping(m_ui.scaleAction, 3); + connect(m_ui.turnAction, SIGNAL(triggered()), m_modeMapper, SLOT(map())); + m_modeMapper->setMapping(m_ui.turnAction, 4); + + connect(m_modeMapper, SIGNAL(mapped(int)), this, SLOT(setMode(int))); + connect(m_ui.pointsAction, SIGNAL(triggered(bool)), m_worldEditorScene, SLOT(setEnabledEditPoints(bool))); + + connect(m_ui.settingsAction, SIGNAL(triggered()), this, SLOT(openProjectSettings())); + connect(m_ui.newWorldEditAction, SIGNAL(triggered()), this, SLOT(newWorldEditFile())); + connect(m_ui.saveWorldEditAction, SIGNAL(triggered()), this, SLOT(saveWorldEditFile())); + connect(m_ui.visibleGridAction, SIGNAL(toggled(bool)), m_ui.graphicsView, SLOT(setVisibleGrid(bool))); + + connect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(updateSelection(QItemSelection, QItemSelection))); + + connect(m_worldEditorScene, SIGNAL(updateSelectedItems(QList)), + this, SLOT(selectedItemsInScene(QList))); + + m_statusBarTimer = new QTimer(this); + connect(m_statusBarTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar())); + + m_statusInfo = new QLabel(this); + m_statusInfo->hide(); + Core::ICore::instance()->mainWindow()->statusBar()->addPermanentWidget(m_statusInfo); +} + +WorldEditorWindow::~WorldEditorWindow() +{ + writeSettings(); + + delete m_zoneBuilderBase; +} + +QUndoStack *WorldEditorWindow::undoStack() const +{ + return m_undoStack; +} + +void WorldEditorWindow::maybeSave() +{ + QMessageBox *messageBox = new QMessageBox(tr("World Editor"), + tr("The data has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, + QMessageBox::No, + QMessageBox::Cancel | QMessageBox::Escape, + this, Qt::Sheet); + + messageBox->setButtonText(QMessageBox::Yes, + tr("Save")); + + messageBox->setButtonText(QMessageBox::No, tr("Don't Save")); + + messageBox->show(); +} + +void WorldEditorWindow::open() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open NeL World Edit file"), m_lastDir, + tr("All NeL World Editor file (*.worldedit)")); + + setCursor(Qt::WaitCursor); + if (!fileName.isEmpty()) + { + m_lastDir = QFileInfo(fileName).absolutePath(); + loadWorldEditFile(fileName); + } + setCursor(Qt::ArrowCursor); +} + +void WorldEditorWindow::loadWorldEditFile(const QString &fileName) +{ + if (m_primitivesModel->isWorldEditNodeLoaded()) + return; + + Utils::WorldEditList worldEditList; + if (!Utils::loadWorldEditFile(fileName.toStdString(), worldEditList)) + { + // TODO: add the message box + return; + } + + m_undoStack->beginMacro(tr("Load %1").arg(fileName)); + + checkCurrentWorld(); + + m_undoStack->push(new CreateWorldCommand(fileName, m_primitivesModel)); + for (size_t i = 0; i < worldEditList.size(); ++i) + { + switch (worldEditList[i].first) + { + case Utils::DataDirectoryType: + m_zoneBuilderBase->init(QString(worldEditList[i].second.c_str()), true); + break; + case Utils::ContextType: + break; + case Utils::LandscapeType: + m_undoStack->push(new LoadLandscapeCommand(QString(worldEditList[i].second.c_str()), m_primitivesModel, m_zoneBuilderBase)); + break; + case Utils::PrimitiveType: + m_undoStack->push(new LoadRootPrimitiveCommand(QString(worldEditList[i].second.c_str()), + m_worldEditorScene, m_primitivesModel, m_ui.treePrimitivesView)); + break; + }; + } + m_undoStack->endMacro(); +} + +void WorldEditorWindow::checkCurrentWorld() +{ +} + +void WorldEditorWindow::newWorldEditFile() +{ + checkCurrentWorld(); + m_undoStack->push(new CreateWorldCommand("NewWorldEdit", m_primitivesModel)); +} + +void WorldEditorWindow::saveWorldEditFile() +{ +} + +void WorldEditorWindow::openProjectSettings() +{ + ProjectSettingsDialog *dialog = new ProjectSettingsDialog(m_zoneBuilderBase->dataPath(), this); + dialog->show(); + int ok = dialog->exec(); + if (ok == QDialog::Accepted) + { + m_zoneBuilderBase->init(dialog->dataPath(), true); + } + delete dialog; +} + +void WorldEditorWindow::setMode(int value) +{ + switch (value) + { + case 0: + m_worldEditorScene->setModeEdit(WorldEditorScene::SelectMode); + break; + case 1: + m_worldEditorScene->setModeEdit(WorldEditorScene::MoveMode); + break; + case 2: + m_worldEditorScene->setModeEdit(WorldEditorScene::RotateMode); + break; + case 3: + m_worldEditorScene->setModeEdit(WorldEditorScene::ScaleMode); + break; + case 4: + m_worldEditorScene->setModeEdit(WorldEditorScene::TurnMode); + break; + case 5: + m_worldEditorScene->setModeEdit(WorldEditorScene::RadiusMode); + break; + } +} + +void WorldEditorWindow::updateStatusBar() +{ + m_statusInfo->setText(m_worldEditorScene->zoneNameFromMousePos()); +} + +void WorldEditorWindow::updateSelection(const QItemSelection &selected, const QItemSelection &deselected) +{ + m_ui.pointsAction->setChecked(false); + m_worldEditorScene->setEnabledEditPoints(false); + + NodeList nodesSelected; + Q_FOREACH(QModelIndex modelIndex, selected.indexes()) + { + Node *node = static_cast(modelIndex.internalPointer()); + nodesSelected.push_back(node); + } + + NodeList nodesDeselected; + Q_FOREACH(QModelIndex modelIndex, deselected.indexes()) + { + Node *node = static_cast(modelIndex.internalPointer()); + nodesDeselected.push_back(node); + } + + // update property editor + if (nodesSelected.size() > 0) + { + // only single selection + m_ui.propertyEditWidget->updateSelection(nodesSelected.at(0)); + } + else + { + m_ui.propertyEditWidget->clearProperties(); + } + + QList itemSelected; + Q_FOREACH(Node *node, nodesSelected) + { + QGraphicsItem *item = getGraphicsItem(node); + if (item != 0) + itemSelected.push_back(item); + } + + QList itemDeselected; + Q_FOREACH(Node *node, nodesDeselected) + { + QGraphicsItem *item = getGraphicsItem(node); + if (item != 0) + itemDeselected.push_back(item); + } + + // Update world editor scene + m_worldEditorScene->updateSelection(itemSelected, itemDeselected); +} + +void WorldEditorWindow::selectedItemsInScene(const QList &selected) +{ + QItemSelectionModel *selectionModel = m_ui.treePrimitivesView->selectionModel(); + disconnect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(updateSelection(QItemSelection, QItemSelection))); + + selectionModel->clear(); + QItemSelection itemSelection; + Q_FOREACH(QGraphicsItem *item, selected) + { + QPersistentModelIndex *index = qvariant_cast(item->data(Constants::NODE_PERISTENT_INDEX)); + if (index->isValid()) + { + QModelIndex modelIndex = index->operator const QModelIndex &(); + QItemSelection mergeItemSelection(modelIndex, modelIndex); + itemSelection.merge(mergeItemSelection, QItemSelectionModel::Select); + } + QApplication::processEvents(); + } + + selectionModel->select(itemSelection, QItemSelectionModel::Select); + + // update property editor + if (!selected.isEmpty()) + { + // only single selection + Node *node = qvariant_cast(selected.at(0)->data(Constants::WORLD_EDITOR_NODE)); + m_ui.propertyEditWidget->updateSelection(node); + } + else + { + m_ui.propertyEditWidget->clearProperties(); + } + + connect(m_ui.treePrimitivesView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, SLOT(updateSelection(QItemSelection, QItemSelection))); +} + +void WorldEditorWindow::showEvent(QShowEvent *showEvent) +{ + QMainWindow::showEvent(showEvent); + if (m_oglWidget != 0) + m_oglWidget->makeCurrent(); + m_statusInfo->show(); + m_statusBarTimer->start(100); +} + +void WorldEditorWindow::hideEvent(QHideEvent *hideEvent) +{ + QMainWindow::hideEvent(hideEvent); + m_statusInfo->hide(); + m_statusBarTimer->stop(); +} + +void WorldEditorWindow::createMenus() +{ + //Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); +} + +void WorldEditorWindow::createToolBars() +{ + Core::MenuManager *menuManager = Core::ICore::instance()->menuManager(); + //QAction *action = menuManager->action(Core::Constants::NEW); + //m_ui.fileToolBar->addAction(action); + + m_ui.fileToolBar->addAction(m_ui.newWorldEditAction); + QAction *action = menuManager->action(Core::Constants::OPEN); + m_ui.fileToolBar->addAction(action); + m_ui.fileToolBar->addAction(m_ui.saveWorldEditAction); + m_ui.fileToolBar->addSeparator(); + + action = menuManager->action(Core::Constants::UNDO); + if (action != 0) + m_ui.fileToolBar->addAction(action); + + action = menuManager->action(Core::Constants::REDO); + if (action != 0) + m_ui.fileToolBar->addAction(action); + + //action = menuManager->action(Core::Constants::SAVE); + //m_ui.fileToolBar->addAction(action); + //action = menuManager->action(Core::Constants::SAVE_AS); + //m_ui.fileToolBar->addAction(action); +} + +void WorldEditorWindow::readSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::WORLD_EDITOR_SECTION); + restoreState(settings->value(Constants::WORLD_WINDOW_STATE).toByteArray()); + restoreGeometry(settings->value(Constants::WORLD_WINDOW_GEOMETRY).toByteArray()); + + // Use OpenGL graphics system instead raster graphics system + if (settings->value(Constants::WORLD_EDITOR_USE_OPENGL, true).toBool()) + { + m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer)); + //m_oglWidget = new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::SampleBuffers)); + m_ui.graphicsView->setViewport(m_oglWidget); + } + + settings->endGroup(); +} + +void WorldEditorWindow::writeSettings() +{ + QSettings *settings = Core::ICore::instance()->settings(); + settings->beginGroup(Constants::WORLD_EDITOR_SECTION); + settings->setValue(Constants::WORLD_WINDOW_STATE, saveState()); + settings->setValue(Constants::WORLD_WINDOW_GEOMETRY, saveGeometry()); + settings->endGroup(); + settings->sync(); +} + +} /* namespace LandscapeEditor */