[darkradiant] 01/06: New upstream version 2.1.0
Tobias Frost
tobi at moszumanska.debian.org
Sun Dec 11 11:47:25 UTC 2016
This is an automated email from the git hooks/post-receive script.
tobi pushed a commit to branch master
in repository darkradiant.
commit d5251fea5fa16186bd6f94588afa84cf5fcb6b1a
Author: Tobias Frost <tobi at coldtobi.de>
Date: Wed Dec 7 08:05:02 2016 +0100
New upstream version 2.1.0
---
.gitignore | 4 +
README | 17 +-
compile | 2 +-
depcomp | 586 ++-
include/editable.h | 46 +-
include/iaasfile.h | 162 +
include/icameraview.h | 12 +
include/ientity.h | 8 +-
include/ientityinspector.h | 5 +
include/igame.h | 6 +
include/igroupdialog.h | 21 +-
include/imap.h | 24 +-
include/imapinfofile.h | 157 +
include/imapresource.h | 33 +-
include/inode.h | 12 +
include/iorthocontextmenu.h | 1 +
include/ipatch.h | 4 +-
include/ipreferencesystem.h | 54 +-
include/irenderable.h | 30 +-
include/iselectable.h | 21 +-
include/iselection.h | 10 +-
include/iselectiongroup.h | 120 +
include/iselectiontest.h | 7 +-
include/iuimanager.h | 4 +-
include/precompiled_interfaces.h | 2 +
include/version.h | 2 +-
install/bitmaps/empty.png | Bin 143 -> 155 bytes
install/bitmaps/group_selection.png | Bin 0 -> 263 bytes
install/bitmaps/ungroup_selection.png | Bin 0 -> 257 bytes
install/i18n/darkradiant.pot | 835 ++--
install/i18n/de/LC_MESSAGES/darkradiant.mo | Bin 97427 -> 99807 bytes
install/i18n/de/LC_MESSAGES/darkradiant.po | 871 ++--
install/input.xml | 6 +-
install/menu.xml | 2 +-
.../commands/check_for_invalid_visportals.py | 69 +
install/ui/findandreplacedialog.fbp | 4 +-
install/ui/findandreplacedialog.xrc | 294 +-
install/ui/particleeditor.fbp | 41 +-
install/ui/particleeditor.xrc | 4286 ++++++++++----------
install/ui/stimeditor.fbp | 17 +-
install/ui/stimeditor.xrc | 4 +-
install/user.xml | 526 +--
libs/ObservedSelectable.h | 13 +-
libs/SelectableNode.h | 52 -
libs/entitylib.h | 10 +-
libs/math/Vector2.h | 6 +
libs/os/file.h | 107 +-
libs/os/path.h | 18 +-
libs/pivot.h | 2 +-
libs/registry/Widgets.h | 28 +-
libs/render/RenderableSpacePartition.h | 10 +-
libs/render/ShaderStateRenderer.h | 5 +-
libs/scene/BasicRootNode.h | 4 +-
libs/scene/Makefile.am | 1 +
libs/scene/Makefile.in | 4 +-
libs/scene/Node.cpp | 35 +-
libs/scene/Node.h | 17 +-
libs/scene/SelectableNode.cpp | 247 ++
libs/scene/SelectableNode.h | 75 +
libs/scene/TraversableNodeSet.cpp | 14 +-
libs/scene/TraversableNodeSet.h | 11 +-
libs/scenelib.h | 5 +-
libs/wxutil/GLWidget.cpp | 5 +-
libs/wxutil/Makefile.am | 2 +
libs/wxutil/Makefile.in | 2 +
libs/wxutil/TreeModel.cpp | 40 +-
libs/wxutil/TreeModel.h | 28 +-
libs/wxutil/TreeView.cpp | 13 +
libs/wxutil/TreeView.h | 1 +
missing | 460 +--
plugins/dm.conversation/ConversationDialog.cpp | 9 +-
plugins/dm.conversation/ConversationDialog.h | 1 +
plugins/dm.conversation/ConversationEditor.cpp | 25 +
plugins/dm.editing/AIEditingPanel.cpp | 10 +-
plugins/dm.editing/AIEditingPanel.h | 4 +-
plugins/dm.editing/AIHeadPropertyEditor.cpp | 5 +
plugins/dm.editing/AIHeadPropertyEditor.h | 5 +-
plugins/dm.editing/AIVocalSetPropertyEditor.cpp | 5 +
plugins/dm.editing/AIVocalSetPropertyEditor.h | 5 +-
plugins/dm.editing/Makefile.am | 6 +-
plugins/dm.editing/Makefile.in | 6 +-
plugins/dm.gui/plugin.cpp | 6 +-
plugins/dm.objectives/ObjectiveEntityFinder.cpp | 2 +-
plugins/dm.stimresponse/EffectEditor.cpp | 2 +-
plugins/entity/Doom3Entity.cpp | 5 +
plugins/entity/Doom3Entity.h | 25 +-
plugins/entity/EntityNode.cpp | 6 +-
plugins/entity/EntityNode.h | 10 +-
plugins/entity/VertexInstance.h | 6 +-
plugins/entity/curve/CurveEditInstance.cpp | 10 +-
plugins/entity/curve/CurveEditInstance.h | 1 +
plugins/entity/doom3group/Doom3Group.cpp | 11 +-
plugins/entity/doom3group/Doom3GroupNode.cpp | 12 +-
plugins/entity/doom3group/Doom3GroupNode.h | 17 +-
plugins/entity/eclassmodel/EclassModelNode.h | 6 +-
plugins/entity/generic/GenericEntityNode.cpp | 7 -
plugins/entity/generic/GenericEntityNode.h | 13 +-
plugins/entity/light/Light.cpp | 14 +-
plugins/entity/light/Light.h | 5 -
plugins/entity/light/LightNode.cpp | 19 +-
plugins/entity/light/LightNode.h | 21 +-
plugins/entity/speaker/SpeakerNode.cpp | 7 +-
plugins/entity/speaker/SpeakerNode.h | 13 +-
plugins/entity/target/TargetLineNode.cpp | 6 +-
plugins/entity/target/TargetLineNode.h | 2 +-
plugins/entity/target/TargetableNode.cpp | 3 +
plugins/entitylist/EntityList.cpp | 2 +-
plugins/entitylist/GraphTreeModelPopulator.h | 2 +-
plugins/eventmanager/MouseToolManager.cpp | 83 +-
plugins/eventmanager/MouseToolManager.h | 2 +-
plugins/fonts/GlyphSet.cpp | 2 +-
plugins/fonts/Makefile.am | 2 +
plugins/fonts/Makefile.in | 2 +
plugins/grid/Grid.cpp | 13 +-
plugins/mapdoom3/Makefile.am | 10 +-
plugins/mapdoom3/Makefile.in | 41 +-
plugins/mapdoom3/aas/Doom3AasFile.cpp | 413 ++
plugins/mapdoom3/aas/Doom3AasFile.h | 65 +
plugins/mapdoom3/aas/Doom3AasFileLoader.cpp | 127 +
plugins/mapdoom3/aas/Doom3AasFileLoader.h | 35 +
plugins/mapdoom3/aas/Doom3AasFileSettings.cpp | 162 +
plugins/mapdoom3/aas/Doom3AasFileSettings.h | 47 +
plugins/mapdoom3/aas/Util.h | 21 +
plugins/mapdoom3/compiler/DebugRenderer.h | 10 +-
plugins/mapdoom3/compiler/Doom3MapCompiler.cpp | 11 +-
plugins/mapdoom3/compiler/OptIsland.cpp | 2 +-
plugins/mapdoom3/compiler/ProcCompiler.cpp | 7 +-
plugins/mapdoom3/compiler/ProcPatch.cpp | 8 -
plugins/mapdoom3/mapdoom3.cpp | 14 +-
.../mapdoom3/primitivewriters/PatchDefExporter.h | 4 +-
plugins/md5model/MD5ModelNode.h | 10 +-
plugins/md5model/MD5Skeleton.cpp | 16 +-
plugins/model/PicoModelNode.h | 10 +-
plugins/particles/ParticleDef.cpp | 3 +
plugins/particles/ParticleDef.h | 31 +-
plugins/particles/ParticleNode.cpp | 4 +-
plugins/particles/ParticleNode.h | 8 +-
plugins/particles/ParticleQuad.h | 10 +-
plugins/particles/ParticlesManager.cpp | 19 +-
plugins/particles/RenderableParticle.h | 10 +-
plugins/particles/RenderableParticleBunch.cpp | 5 +-
plugins/particles/StageDef.cpp | 19 +-
plugins/script/ScriptingSystem.cpp | 2 +-
plugins/script/interfaces/PatchInterface.cpp | 7 +-
plugins/script/interfaces/SceneGraphInterface.h | 10 +-
plugins/shaders/Doom3ShaderSystem.cpp | 6 +-
plugins/shaders/textures/TextureManipulator.cpp | 9 +-
plugins/sound/WavFileLoader.h | 16 +-
plugins/uimanager/GroupDialog.cpp | 59 +-
plugins/uimanager/GroupDialog.h | 4 +-
plugins/uimanager/Makefile.am | 2 +
plugins/uimanager/Makefile.in | 2 +
plugins/uimanager/MenuManager.cpp | 4 +-
plugins/uimanager/StatusBarManager.cpp | 13 +-
plugins/uimanager/StatusBarManager.h | 13 +-
plugins/uimanager/ToolbarManager.cpp | 2 +-
plugins/uimanager/UIManager.cpp | 4 +-
plugins/undo/UndoSystem.cpp | 18 +-
plugins/xmlregistry/Makefile.am | 6 +-
plugins/xmlregistry/Makefile.in | 6 +-
radiant/Makefile.am | 16 +-
radiant/Makefile.in | 335 +-
radiant/RadiantModule.cpp | 21 +-
radiant/RadiantModule.h | 7 +-
radiant/brush/Brush.cpp | 5 +-
radiant/brush/BrushModule.cpp | 6 +-
radiant/brush/BrushNode.cpp | 84 +-
radiant/brush/BrushNode.h | 26 +-
radiant/brush/EdgeInstance.h | 2 +-
radiant/brush/FaceInstance.cpp | 8 +-
radiant/brush/FaceInstance.h | 2 +-
radiant/brush/TextureProjection.cpp | 8 +-
radiant/brush/VertexInstance.h | 2 +-
radiant/brush/csg/CSG.cpp | 8 +-
radiant/camera/CamRenderer.cpp | 17 +-
radiant/camera/CamRenderer.h | 3 +-
radiant/camera/CamWnd.cpp | 33 +-
radiant/camera/CamWnd.h | 13 +-
radiant/camera/CameraSettings.cpp | 20 +-
radiant/camera/GlobalCamera.cpp | 2 +
radiant/camera/tools/PanViewTool.h | 89 +
radiant/clipper/Clipper.cpp | 6 +-
radiant/darkradiant.rc | 23 +
radiant/layers/LayerInfoFileModule.cpp | 282 ++
radiant/layers/LayerInfoFileModule.h | 54 +
radiant/layers/LayerSystem.cpp | 21 +-
radiant/layers/LayerSystem.h | 3 +
radiant/layers/SetLayerSelectedWalker.h | 5 +-
radiant/map/AasFileManager.cpp | 170 +
radiant/map/AasFileManager.h | 41 +
radiant/map/AutoSaver.cpp | 167 +-
radiant/map/AutoSaver.h | 28 +-
radiant/map/CounterManager.cpp | 23 +-
radiant/map/CounterManager.h | 16 +-
radiant/map/DeferredDraw.h | 63 -
radiant/map/InfoFile.cpp | 308 --
radiant/map/InfoFile.h | 99 -
radiant/map/Map.cpp | 325 +-
radiant/map/Map.h | 65 +-
radiant/map/MapResource.cpp | 332 +-
radiant/map/MapResource.h | 58 +-
radiant/map/MapResourceManager.cpp | 9 +-
radiant/map/MapResourceManager.h | 9 +-
radiant/map/PointFile.cpp | 10 +
radiant/map/PointFile.h | 21 +-
radiant/map/RegionManager.cpp | 171 +-
radiant/map/RegionManager.h | 85 +-
radiant/map/RenderableAasFile.cpp | 121 +
radiant/map/RenderableAasFile.h | 56 +
radiant/map/RootNode.h | 8 +-
radiant/map/algorithm/AssignLayerMappingWalker.h | 48 -
radiant/map/algorithm/ChildPrimitives.cpp | 4 +-
radiant/map/algorithm/Clone.h | 5 +
radiant/map/algorithm/InfoFileExporter.cpp | 169 -
radiant/map/algorithm/InfoFileExporter.h | 66 -
radiant/map/algorithm/MapExporter.h | 2 +-
radiant/map/algorithm/MapImporter.cpp | 14 +-
radiant/map/algorithm/MapImporter.h | 12 +-
radiant/map/algorithm/Merge.h | 4 +-
radiant/map/algorithm/WorldspawnArgFinder.h | 2 +-
radiant/map/infofile/InfoFile.cpp | 143 +
radiant/map/infofile/InfoFile.h | 45 +
radiant/map/infofile/InfoFileExporter.cpp | 62 +
radiant/map/infofile/InfoFileExporter.h | 31 +
radiant/map/infofile/InfoFileManager.cpp | 67 +
radiant/map/infofile/InfoFileManager.h | 29 +
radiant/modulesystem/ModuleRegistry.cpp | 6 +-
radiant/patch/Patch.cpp | 2301 +++--------
radiant/patch/Patch.h | 119 +-
radiant/patch/PatchBezier.cpp | 184 -
radiant/patch/PatchBezier.h | 80 -
radiant/patch/PatchCreators.cpp | 5 +-
radiant/patch/PatchModule.cpp | 39 -
radiant/patch/PatchNode.cpp | 56 +-
radiant/patch/PatchNode.h | 25 +-
radiant/patch/PatchRenderables.cpp | 154 +-
radiant/patch/PatchRenderables.h | 68 +-
radiant/patch/PatchTesselation.cpp | 871 ++++
radiant/patch/PatchTesselation.h | 65 +-
radiant/referencecache/NullModelNode.h | 10 +-
radiant/render/backend/GLProgramFactory.cpp | 2 +-
radiant/render/backend/OpenGLShader.cpp | 30 +
.../render/frontend/RenderableCollectionWalker.h | 19 +-
radiant/selection/BasicSelectable.h | 2 +-
radiant/selection/Device.h | 46 +-
radiant/selection/DragManipulator.cpp | 2 +-
radiant/selection/OccludeSelector.h | 2 +-
radiant/selection/RadiantSelectionSystem.cpp | 269 +-
radiant/selection/RadiantSelectionSystem.h | 34 +-
radiant/selection/SceneWalkers.h | 18 -
radiant/selection/SelectionTest.cpp | 4 +-
radiant/selection/Selectors.h | 29 +-
radiant/selection/TransformationVisitors.cpp | 7 +-
radiant/selection/TranslateManipulator.cpp | 2 +-
.../algorithm/CommandNotAvailableException.h | 50 +
radiant/selection/algorithm/Entity.cpp | 151 +-
radiant/selection/algorithm/Entity.h | 10 +
radiant/selection/algorithm/General.cpp | 130 +-
radiant/selection/algorithm/Group.cpp | 139 +-
radiant/selection/algorithm/Group.h | 30 +-
radiant/selection/algorithm/GroupCycle.cpp | 2 +-
radiant/selection/algorithm/Patch.cpp | 11 -
radiant/selection/algorithm/Patch.h | 2 -
radiant/selection/algorithm/Primitives.cpp | 4 +-
radiant/selection/algorithm/Transformation.cpp | 101 +-
radiant/selection/group/SelectionGroup.h | 120 +
.../group/SelectionGroupInfoFileModule.cpp | 342 ++
.../selection/group/SelectionGroupInfoFileModule.h | 59 +
radiant/selection/group/SelectionGroupManager.cpp | 280 ++
radiant/selection/group/SelectionGroupManager.h | 62 +
.../selectionset/SelectionSetInfoFileModule.cpp | 230 ++
.../selectionset/SelectionSetInfoFileModule.h | 61 +
.../selection/selectionset/SelectionSetManager.cpp | 22 +-
.../selection/selectionset/SelectionSetManager.h | 2 +
.../selection/shaderclipboard/ShaderClipboard.cpp | 14 +-
.../selection/shaderclipboard/ShaderClipboard.h | 5 +-
radiant/settings/GameManager.cpp | 16 +-
radiant/settings/GameManager.h | 26 +-
radiant/settings/LanguageManager.cpp | 6 +-
radiant/settings/PreferenceItemBase.h | 44 +
radiant/settings/PreferenceItems.h | 170 +
radiant/settings/PreferencePage.cpp | 159 +
radiant/settings/PreferencePage.h | 94 +
radiant/settings/PreferenceSystem.cpp | 74 +-
radiant/settings/PreferenceSystem.h | 46 +-
radiant/textool/item/PatchItem.cpp | 4 +-
radiant/ui/aas/AasControl.cpp | 123 +
radiant/ui/aas/AasControl.h | 63 +
radiant/ui/aas/AasControlDialog.cpp | 237 ++
radiant/ui/aas/AasControlDialog.h | 65 +
radiant/ui/einspector/AnglePropertyEditor.h | 2 +-
radiant/ui/einspector/BooleanPropertyEditor.cpp | 8 +-
radiant/ui/einspector/BooleanPropertyEditor.h | 4 +-
radiant/ui/einspector/ClassnamePropertyEditor.cpp | 12 +-
radiant/ui/einspector/ClassnamePropertyEditor.h | 2 +-
radiant/ui/einspector/ColourPropertyEditor.cpp | 7 +-
radiant/ui/einspector/ColourPropertyEditor.h | 4 +-
radiant/ui/einspector/EntityInspector.cpp | 426 +-
radiant/ui/einspector/EntityInspector.h | 19 +-
radiant/ui/einspector/EntityPropertyEditor.cpp | 5 +
radiant/ui/einspector/EntityPropertyEditor.h | 4 +-
radiant/ui/einspector/FloatPropertyEditor.cpp | 28 +-
radiant/ui/einspector/FloatPropertyEditor.h | 4 +-
radiant/ui/einspector/ModelPropertyEditor.h | 2 +-
radiant/ui/einspector/PropertyEditor.h | 7 +-
radiant/ui/einspector/SkinPropertyEditor.h | 2 +-
radiant/ui/einspector/SoundPropertyEditor.h | 2 +-
radiant/ui/einspector/TexturePropertyEditor.h | 2 +-
radiant/ui/einspector/Vector3PropertyEditor.cpp | 7 +-
radiant/ui/einspector/Vector3PropertyEditor.h | 4 +-
radiant/ui/layers/LayerControl.cpp | 2 +-
radiant/ui/mainframe/EmbeddedLayout.cpp | 1 +
radiant/ui/mainframe/FloatingLayout.cpp | 1 +
radiant/ui/mainframe/MainFrame.cpp | 62 +-
radiant/ui/mainframe/MainFrame.h | 1 -
radiant/ui/mainframe/ScreenUpdateBlocker.cpp | 9 +-
radiant/ui/mainframe/SplitPaneLayout.cpp | 1 +
radiant/ui/mediabrowser/MediaBrowser.cpp | 4 +-
radiant/ui/mru/MRU.cpp | 6 +-
radiant/ui/ortho/OrthoContextMenu.cpp | 7 +-
radiant/ui/overlay/Overlay.cpp | 1 +
radiant/ui/patch/PatchInspector.cpp | 4 +-
radiant/ui/prefabselector/PrefabSelector.cpp | 39 +-
radiant/ui/prefabselector/PrefabSelector.h | 15 +-
radiant/ui/prefdialog/PrefDialog.cpp | 227 +-
radiant/ui/prefdialog/PrefDialog.h | 50 +-
radiant/ui/prefdialog/PrefPage.cpp | 364 +-
radiant/ui/prefdialog/PrefPage.h | 125 +-
radiant/ui/prefdialog/PreferenceItem.cpp | 164 +
radiant/ui/prefdialog/PreferenceItem.h | 47 +
radiant/ui/texturebrowser/TextureBrowser.cpp | 80 +-
.../ui/texturebrowser/TextureBrowserManager.cpp | 12 +-
radiant/xyview/GlobalXYWnd.cpp | 37 +-
radiant/xyview/XYRenderer.h | 56 +-
radiant/xyview/XYWnd.cpp | 37 +-
radiant/xyview/XYWnd.h | 7 +-
tools/i18n/darkradiant.pot | 835 ++--
tools/innosetup/create_installer.x64.cmd | 2 -
tools/innosetup/create_installer.x86.cmd | 2 -
tools/innosetup/darkradiant.iss | 11 +-
tools/innosetup/darkradiant.x64.iss | 10 +-
tools/{msvc2013 => msvc2015}/DarkRadiant.sln | 0
tools/{msvc2013 => msvc2015}/DarkRadiant.vcxproj | 61 +-
.../DarkRadiant.vcxproj.filters | 137 +-
tools/{msvc2013 => msvc2015}/archivezip.vcxproj | 10 +-
.../archivezip.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/commandsystem.vcxproj | 10 +-
.../commandsystem.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/ddslib.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/dm.conversation.vcxproj | 10 +-
.../dm.conversation.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/dm.difficulty.vcxproj | 10 +-
.../dm.difficulty.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/dm.editing.vcxproj | 10 +-
.../dm.editing.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/dm.gui.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/dm.gui.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/dm.objectives.vcxproj | 10 +-
.../dm.objectives.vcxproj.filters | 0
.../{msvc2013 => msvc2015}/dm.stimresponse.vcxproj | 10 +-
.../dm.stimresponse.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/eclassmgr.vcxproj | 10 +-
.../eclassmgr.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/eclasstree.vcxproj | 10 +-
.../eclasstree.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/entity.vcxproj | 18 +-
.../{msvc2013 => msvc2015}/entity.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/entitylist.vcxproj | 10 +-
.../entitylist.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/eventmanager.vcxproj | 10 +-
.../eventmanager.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/filetypes.vcxproj | 10 +-
.../filetypes.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/filters.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/filters.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/fonts.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/fonts.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/grid.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/grid.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/image.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/image.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/include.vcxproj | 21 +-
tools/{msvc2013 => msvc2015}/libs.vcxproj | 11 +-
tools/{msvc2013 => msvc2015}/libs.vcxproj.filters | 1 -
tools/{msvc2013 => msvc2015}/mapdoom3.vcxproj | 17 +-
.../mapdoom3.vcxproj.filters | 24 +
tools/{msvc2013 => msvc2015}/mathlib.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/md5model.vcxproj | 10 +-
.../md5model.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/model.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/model.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/particles.vcxproj | 10 +-
.../particles.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/picomodellib.vcxproj | 10 +-
.../picomodellib.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/post_build_event.cmd | 16 +-
.../post_build_event_x64.cmd | 16 +-
.../{msvc2013 => msvc2015}/properties/Boost.props | 0
.../properties/DarkRadiant Base Debug Win32.props | 0
.../properties/DarkRadiant Base Debug x64.props | 3 +
.../DarkRadiant Base Release Win32.props | 0
.../properties/DarkRadiant Base Release x64.props | 6 +-
.../properties/DarkRadiant Base.props | 0
tools/{msvc2013 => msvc2015}/properties/GLEW.props | 0
.../properties/OpenAL + Vorbis.props | 0
.../{msvc2013 => msvc2015}/properties/Python.props | 0
tools/{msvc2013 => msvc2015}/properties/ftgl.props | 0
.../{msvc2013 => msvc2015}/properties/libpng.props | 0
.../properties/libxml2.props | 0
.../properties/win_iconv.props | 0
.../properties/wxWidgets.props | 0
tools/{msvc2013 => msvc2015}/properties/zlib.props | 0
tools/{msvc2013 => msvc2015}/scenegraph.vcxproj | 10 +-
.../scenegraph.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/scenelib.vcxproj | 12 +-
.../scenelib.vcxproj.filters | 6 +
tools/{msvc2013 => msvc2015}/script.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/script.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/shaders.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/shaders.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/skins.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/skins.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/sound.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/sound.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/uimanager.vcxproj | 10 +-
.../uimanager.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/undo.vcxproj | 10 +-
tools/{msvc2013 => msvc2015}/undo.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/vfspk3.vcxproj | 10 +-
.../{msvc2013 => msvc2015}/vfspk3.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/wavefront.vcxproj | 0
.../wavefront.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/wxutillib.vcxproj | 10 +-
.../wxutillib.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/xmlregistry.vcxproj | 10 +-
.../xmlregistry.vcxproj.filters | 0
tools/{msvc2013 => msvc2015}/xmlutillib.vcxproj | 10 +-
tools/scripts/build_boost_libs.cmd | 35 +-
tools/scripts/build_boost_libs.x64.cmd | 35 +-
tools/scripts/compile_release_package.ps1 | 57 +-
tools/scripts/copy_install_files.cmd | 10 -
tools/scripts/copy_install_files.x64.cmd | 10 -
442 files changed, 15623 insertions(+), 10618 deletions(-)
diff --git a/.gitignore b/.gitignore
index 60268e0..1810829 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,7 @@ testsuite.ilk
/tools/innosetup/*.7z
*.vspx
*.bak
+*.opendb
+tools/msvc2015/DarkRadiant.VC.db
+*.iobj
+*.ipdb
diff --git a/README b/README
index 9706fa7..0258444 100644
--- a/README
+++ b/README
@@ -10,11 +10,11 @@ Compiling on Windows
Prerequisites
-------------
-DarkRadiant is built on Windows using Microsoft Visual C++ 2013.
-The free Express version can be obtained here:
+DarkRadiant is built on Windows using Microsoft Visual C++ 2015.
+The free Community Edition can be obtained here:
-VC++ 2013: http://www.visualstudio.com/de-de/downloads
- (Choose Visual Studio Express 2013 for Windows Desktop)
+VC++ 2015: https://www.visualstudio.com/en-us/downloads
+ (Choose Visual Studio Community)
Since DarkRadiant uses a couple of open-source libraries that are not available on
Windows by default, you will also need to download and install the
@@ -22,11 +22,11 @@ dependencies. 7-Zip packages of the dependencies are available at the following
URL(s). (Get 7-zip here: http://www.7-zip.org/)
32-bit only builds:
-https://github.com/codereader/DarkRadiant/releases/download/2.0.0/w32deps.7z
+https://github.com/codereader/DarkRadiant/releases/download/2.1.0/w32deps.7z
64-bit builds:
-https://github.com/codereader/DarkRadiant/releases/download/2.0.0/w32deps.7z
-https://github.com/codereader/DarkRadiant/releases/download/2.0.0/w64deps.7z
+https://github.com/codereader/DarkRadiant/releases/download/2.1.0/w32deps.7z
+https://github.com/codereader/DarkRadiant/releases/download/2.1.0/w64deps.7z
Note that 64-bit builds need the 32-bit dependencies in addition to their own
64-bit dependencies.
@@ -39,7 +39,7 @@ Build
The main Visual C++ solution file is:
-Visual Studio 2013: tools/msvc2013/DarkRadiant.sln
+Visual Studio 2015: tools/msvc2015/DarkRadiant.sln
Open this file with Visual Studio and start a build by right-clicking on the
top-level "Solution 'DarkRadiant'" item and choosing Build Solution.
@@ -82,6 +82,7 @@ Build
To build DarkRadiant the standard Autotools build process is used:
+$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
diff --git a/compile b/compile
old mode 100644
new mode 100755
index 531136b..a85b723
--- a/compile
+++ b/compile
@@ -3,7 +3,7 @@
scriptversion=2012-10-14.11; # UTC
-# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey at cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
diff --git a/depcomp b/depcomp
index e5f9736..fc98710 100755
--- a/depcomp
+++ b/depcomp
@@ -1,10 +1,9 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
-scriptversion=2007-03-29.01
+scriptversion=2013-05-30.07; # UTC
-# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
-# Foundation, Inc.
+# Copyright (C) 1999-2014 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,9 +16,7 @@ scriptversion=2007-03-29.01
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -30,9 +27,9 @@ scriptversion=2007-03-29.01
case $1 in
'')
- echo "$0: No command. Try \`$0 --help' for more information." 1>&2
- exit 1;
- ;;
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
@@ -42,11 +39,11 @@ as side-effects.
Environment variables:
depmode Dependency tracking mode.
- source Source file read by `PROGRAMS ARGS'.
- object Object file output by `PROGRAMS ARGS'.
+ source Source file read by 'PROGRAMS ARGS'.
+ object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
- tmpdepfile Temporary file to use when outputing dependencies.
+ tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake at gnu.org>.
@@ -59,6 +56,66 @@ EOF
;;
esac
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'. Note that this directory component will
+# be either empty or ending with a '/' character. This is deliberate.
+set_dir_from ()
+{
+ case $1 in
+ */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+ *) dir=;;
+ esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+ base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+ echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+ # If the compiler actually managed to produce a dependency file,
+ # post-process it.
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form 'foo.o: dependency.h'.
+ # Do two passes, one to just change these to
+ # $object: dependency.h
+ # and one to simply output
+ # dependency.h:
+ # which is needed to avoid the deleted-header problem.
+ { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+ sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+ } > "$depfile"
+ rm -f "$tmpdepfile"
+ else
+ make_dummy_depfile
+ fi
+}
+
+# A tabulation character.
+tab=' '
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
@@ -71,6 +128,9 @@ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
@@ -82,9 +142,32 @@ if test "$depmode" = hp; then
fi
if test "$depmode" = dashXmstdout; then
- # This is just like dashmstdout with a different argument.
- dashmflag=-xM
- depmode=dashmstdout
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+ # This is just like msvc7 but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+ gccflag=-qmakedep=gcc,-MF
+ depmode=gcc
fi
case "$depmode" in
@@ -107,8 +190,7 @@ gcc3)
done
"$@"
stat=$?
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -116,13 +198,17 @@ gcc3)
;;
gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-## -MM, not -M (despite what the docs say).
+## -MM, not -M (despite what the docs say). Also, it might not be
+## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
@@ -130,31 +216,31 @@ gcc)
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
- alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
-## The second -e expression handles DOS-style file names with drive letters.
+ # The second -e expression handles DOS-style file names with drive
+ # letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
- tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'. On the theory
+## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
-## well.
+## well. hp depmode also adds that space, but also prefixes the VPATH
+## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -172,8 +258,7 @@ sgi)
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -181,43 +266,41 @@ sgi)
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
-
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
- # the IRIX cc adds comments like `#:fec' to the end of the
+ # the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
- tr '
-' ' ' >> $depfile
- echo >> $depfile
-
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+ | tr "$nl" ' ' >> "$depfile"
+ echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
- tr ' ' '
-' < "$tmpdepfile" \
- | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
- >> $depfile
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
+ make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
+xlc)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
- # current directory. Also, the AIX compiler puts `$object:' at the
+ # current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
- dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
- test "x$dir" = "x$object" && dir=
- base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ set_dir_from "$object"
+ set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
@@ -230,9 +313,7 @@ aix)
"$@" -M
fi
stat=$?
-
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
@@ -241,44 +322,100 @@ aix)
do
test -f "$tmpdepfile" && break
done
- if test -f "$tmpdepfile"; then
- # Each line is of the form `foo.o: dependent.h'.
- # Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
- else
- # The sourcefile does not contain any dependencies, so just
- # store a dummy comment line, to avoid errors with the Makefile
- # "include basename.Plo" scheme.
- echo "#dummy" > "$depfile"
+ aix_post_process_depfile
+ ;;
+
+tcc)
+ # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+ # FIXME: That version still under development at the moment of writing.
+ # Make that this statement remains true also for stable, released
+ # versions.
+ # It will wrap lines (doesn't matter whether long or short) with a
+ # trailing '\', as in:
+ #
+ # foo.o : \
+ # foo.c \
+ # foo.h \
+ #
+ # It will put a trailing '\' even on the last line, and will use leading
+ # spaces rather than leading tabs (at least since its commit 0394caf7
+ # "Emit spaces for -MD").
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
fi
+ rm -f "$depfile"
+ # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+ # We have to change lines of the first kind to '$object: \'.
+ sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+ # And for each line of the second kind, we have to emit a 'dep.h:'
+ # dummy dependency, to avoid the deleted-header problem.
+ sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
-icc)
- # Intel's C compiler understands `-MD -MF file'. However on
- # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
- # ICC 7.0 will fill foo.d with something like
- # foo.o: sub/foo.c
- # foo.o: sub/foo.h
- # which is wrong. We want:
- # sub/foo.o: sub/foo.c
- # sub/foo.o: sub/foo.h
- # sub/foo.c:
- # sub/foo.h:
- # ICC 7.1 will output
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file. A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+ # Portland's C compiler understands '-MD'.
+ # Will always output deps to 'file.d' where file is the root name of the
+ # source file under compilation, even if file resides in a subdirectory.
+ # The object file name does not affect the name of the '.d' file.
+ # pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
- # and will wrap long lines using \ :
+ # and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
+ set_dir_from "$object"
+ # Use the source, not the object, to determine the base name, since
+ # that's sadly what pgcc will do too.
+ set_base_from "$source"
+ tmpdepfile=$base.d
+
+ # For projects that build the same source file twice into different object
+ # files, the pgcc approach of using the *source* file root name can cause
+ # problems in parallel builds. Use a locking strategy to avoid stomping on
+ # the same $tmpdepfile.
+ lockdir=$base.d-lock
+ trap "
+ echo '$0: caught signal, cleaning up...' >&2
+ rmdir '$lockdir'
+ exit 1
+ " 1 2 13 15
+ numtries=100
+ i=$numtries
+ while test $i -gt 0; do
+ # mkdir is a portable test-and-set.
+ if mkdir "$lockdir" 2>/dev/null; then
+ # This process acquired the lock.
+ "$@" -MD
+ stat=$?
+ # Release the lock.
+ rmdir "$lockdir"
+ break
+ else
+ # If the lock is being held by a different process, wait
+ # until the winning process is done or we timeout.
+ while test -d "$lockdir" && test $i -gt 0; do
+ sleep 1
+ i=`expr $i - 1`
+ done
+ fi
+ i=`expr $i - 1`
+ done
+ trap - 1 2 13 15
+ if test $i -le 0; then
+ echo "$0: failed to acquire lock after $numtries attempts" >&2
+ echo "$0: check lockdir '$lockdir'" >&2
+ exit 1
+ fi
- "$@" -MD -MF "$tmpdepfile"
- stat=$?
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
@@ -290,8 +427,8 @@ icc)
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
- sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
- sed -e 's/$/ :/' >> "$depfile"
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+ | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -302,9 +439,8 @@ hp2)
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
- dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
- test "x$dir" = "x$object" && dir=
- base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ set_dir_from "$object"
+ set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
@@ -315,8 +451,7 @@ hp2)
"$@" +Maked
fi
stat=$?
- if test $stat -eq 0; then :
- else
+ if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
@@ -326,72 +461,107 @@ hp2)
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
- sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
- # Add `dependent.h:' lines.
- sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add 'dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
else
- echo "#dummy" > "$depfile"
+ make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
- # The Tru64 compiler uses -MD to generate dependencies as a side
- # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
- # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
- # dependencies in `foo.d' instead, so we check for that too.
- # Subdirectories are respected.
- dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
- test "x$dir" = "x$object" && dir=
- base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
-
- if test "$libtool" = yes; then
- # With Tru64 cc, shared objects can also be used to make a
- # static library. This mechanism is used in libtool 1.4 series to
- # handle both shared and static libraries in a single compilation.
- # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
- #
- # With libtool 1.5 this exception was removed, and libtool now
- # generates 2 separate objects for the 2 libraries. These two
- # compilations output dependencies in $dir.libs/$base.o.d and
- # in $dir$base.o.d. We have to check for both files, because
- # one of the two compilations can be disabled. We should prefer
- # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
- # automatically cleaned when .libs/ is deleted, while ignoring
- # the former would cause a distcleancheck panic.
- tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
- tmpdepfile2=$dir$base.o.d # libtool 1.5
- tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
- tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
- "$@" -Wc,-MD
- else
- tmpdepfile1=$dir$base.o.d
- tmpdepfile2=$dir$base.d
- tmpdepfile3=$dir$base.d
- tmpdepfile4=$dir$base.d
- "$@" -MD
- fi
-
- stat=$?
- if test $stat -eq 0; then :
- else
- rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
- exit $stat
- fi
-
- for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
- do
- test -f "$tmpdepfile" && break
- done
- if test -f "$tmpdepfile"; then
- sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
- # That's a tab and a space in the [].
- sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
- else
- echo "#dummy" > "$depfile"
- fi
- rm -f "$tmpdepfile"
- ;;
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in 'foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ set_dir_from "$object"
+ set_base_from "$object"
+
+ if test "$libtool" = yes; then
+ # Libtool generates 2 separate objects for the 2 libraries. These
+ # two compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir$base.o.d # libtool 1.5
+ tmpdepfile2=$dir.libs/$base.o.d # Likewise.
+ tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ # Same post-processing that is required for AIX mode.
+ aix_post_process_depfile
+ ;;
+
+msvc7)
+ if test "$libtool" = yes; then
+ showIncludes=-Wc,-showIncludes
+ else
+ showIncludes=-showIncludes
+ fi
+ "$@" $showIncludes > "$tmpdepfile"
+ stat=$?
+ grep -v '^Note: including file: ' "$tmpdepfile"
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The first sed program below extracts the file names and escapes
+ # backslashes for cygpath. The second sed program outputs the file
+ # name when reading, but also accumulates all include files in the
+ # hold buffer in order to output them again at the end. This only
+ # works with sed implementations that can handle large buffers.
+ sed < "$tmpdepfile" -n '
+/^Note: including file: *\(.*\)/ {
+ s//\1/
+ s/\\/\\\\/g
+ p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+ s/.*/'"$tab"'/
+ G
+ p
+}' >> "$depfile"
+ echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+ rm -f "$tmpdepfile"
+ ;;
+
+msvc7msys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
@@ -404,13 +574,13 @@ dashmstdout)
# Remove the call to Libtool.
if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
+ while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
@@ -430,18 +600,18 @@ dashmstdout)
done
test -z "$dashmflag" && dashmflag=-M
- # Require at least two characters before searching for `:'
+ # Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
- # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
- sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
- tr ' ' '
-' < "$tmpdepfile" | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this sed invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
@@ -455,41 +625,51 @@ makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
+ while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
- cleared=no
- for arg in "$@"; do
+ cleared=no eat=no
+ for arg
+ do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
- obj_suffix="`echo $object | sed 's/^.*\././'`"
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
- cat < "$tmpdepfile" > "$depfile"
- sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
-## Some versions of the HPUX 10.20 sed can't process this invocation
-## correctly. Breaking it into two sed invocations is a workaround.
- sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ # makedepend may prepend the VPATH from the source file name to the object.
+ # No need to regex-escape $object, excess matching of '.' is harmless.
+ sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process the last invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed '1,2d' "$tmpdepfile" \
+ | tr ' ' "$nl" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
@@ -500,13 +680,13 @@ cpp)
# Remove the call to Libtool.
if test "$libtool" = yes; then
- while test $1 != '--mode=compile'; do
+ while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
- # Remove `-o $object'.
+ # Remove '-o $object'.
IFS=" "
for arg
do
@@ -525,10 +705,10 @@ cpp)
esac
done
- "$@" -E |
- sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
- -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
- sed '$ s: \\$::' > "$tmpdepfile"
+ "$@" -E \
+ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ | sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
@@ -538,35 +718,56 @@ cpp)
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
- # always write the preprocessed file to stdout, regardless of -o,
- # because we must use -o when running libtool.
+ # always write the preprocessed file to stdout.
"$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
IFS=" "
for arg
do
case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
- set fnord "$@"
- shift
- shift
- ;;
+ set fnord "$@"
+ shift
+ shift
+ ;;
*)
- set fnord "$@" "$arg"
- shift
- shift
- ;;
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
esac
done
- "$@" -E |
- sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
- echo " " >> "$depfile"
- . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+ echo "$tab" >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
none)
exec "$@"
;;
@@ -585,5 +786,6 @@ exit 0
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
# End:
diff --git a/include/editable.h b/include/editable.h
index df49470..d150ed9 100644
--- a/include/editable.h
+++ b/include/editable.h
@@ -1,49 +1,9 @@
-/*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
+#pragma once
-This file is part of GtkRadiant.
-
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-GtkRadiant 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#if !defined(INCLUDED_EDITABLE_H)
-#define INCLUDED_EDITABLE_H
-
-template<typename Element> class BasicVector3;
-typedef BasicVector3<double> Vector3;
-template<typename Element> class BasicVector4;
-typedef BasicVector4<double> Vector4;
-class Matrix4;
-class Quaternion;
+class AABB;
#include "inode.h"
-class Editable
-{
-public:
- virtual ~Editable() {}
- virtual const Matrix4& getLocalPivot() const = 0;
-};
-typedef std::shared_ptr<Editable> EditablePtr;
-
-inline EditablePtr Node_getEditable(const scene::INodePtr& node)
-{
- return std::dynamic_pointer_cast<Editable>(node);
-}
-
class Snappable
{
public:
@@ -80,5 +40,3 @@ inline ComponentSnappablePtr Node_getComponentSnappable(const scene::INodePtr& n
{
return std::dynamic_pointer_cast<ComponentSnappable>(node);
}
-
-#endif
diff --git a/include/iaasfile.h b/include/iaasfile.h
new file mode 100644
index 0000000..46c61cb
--- /dev/null
+++ b/include/iaasfile.h
@@ -0,0 +1,162 @@
+#pragma once
+
+#include <memory>
+#include "imodule.h"
+#include <list>
+
+#include "math/Plane3.h"
+#include "math/Vector3.h"
+#include "math/AABB.h"
+
+namespace map
+{
+
+// An AAS type is defined by an entityDef block
+// Each AAS type has its own file extension
+struct AasType
+{
+ std::string entityDefName;
+ std::string fileExtension;
+};
+typedef std::list<AasType> AasTypeList;
+
+/**
+ * Representation of a Area Awareness System file.
+ * Provides read-only access to Area and Portal information.
+ * Use the GlobalAasFileManager() to acquire an instance of
+ * this class.
+ */
+class IAasFile
+{
+public:
+ virtual std::size_t getNumPlanes() const = 0;
+ virtual const Plane3& getPlane(std::size_t planeNum) const = 0;
+
+ virtual std::size_t getNumVertices() const = 0;
+ virtual const Vector3& getVertex(std::size_t vertexNum) const = 0;
+
+ // An edge references two vertices by index
+ struct Edge
+ {
+ int vertexNumber[2];
+ };
+
+ virtual std::size_t getNumEdges() const = 0;
+ virtual const Edge& getEdge(std::size_t index) const = 0;
+
+ virtual std::size_t getNumEdgeIndexes() const = 0;
+ virtual int getEdgeByIndex(int edgeIdx) const = 0;
+
+ struct Face
+ {
+ int planeNum; // number of the plane this face is on
+ unsigned short flags; // face flags
+ int numEdges; // number of edges in the boundary of the face
+ int firstEdge; // first edge in the edge index
+ short areas[2]; // area at the front and back of this face
+ };
+
+ virtual std::size_t getNumFaces() const = 0;
+ virtual const Face& getFace(int faceIndex) const = 0;
+ virtual std::size_t getNumFaceIndexes() const = 0;
+ virtual int getFaceByIndex(int faceIdx) const = 0;
+
+ struct Area
+ {
+ int numFaces; // number of faces used for the boundary of the area
+ int firstFace; // first face in the face index used for the boundary of the area
+ AABB bounds; // bounds of the area
+ Vector3 center; // center of the area an AI can move towards
+ unsigned short flags; // several area flags
+ unsigned short contents; // contents of the area
+ short cluster; // cluster the area belongs to, if negative it's a portal
+ short clusterAreaNum; // number of the area in the cluster
+ int travelFlags; // travel flags for traveling through this area
+ };
+
+ virtual std::size_t getNumAreas() const = 0;
+ virtual const Area& getArea(int areaNum) const = 0;
+};
+typedef std::shared_ptr<IAasFile> IAasFilePtr;
+
+/**
+ * A loader class capable of constructing an IAasFile instance from a token stream.
+ */
+class IAasFileLoader :
+ public RegisterableModule
+{
+public:
+ /**
+ * Get the display name of this AAS file loader, e.g. "Doom 3", "Quake 4", etc.
+ */
+ virtual const std::string& getAasFormatName() const = 0;
+
+ /**
+ * Each MapFormat can have a certain game type it is designed for,
+ * a value which conincides with the type attribute in the game tag
+ * found in the .game file, e.g. "doom3" or "quake4".
+ */
+ virtual const std::string& getGameType() const = 0;
+
+ /**
+ * greebo: Returns true if this loader is able to parse
+ * the contents of this file. Usually this includes a version
+ * check of the file header.
+ */
+ virtual bool canLoad(std::istream& stream) const = 0;
+
+ /**
+ * Load the AAS file contents from the given stream.
+ */
+ virtual IAasFilePtr loadFromStream(std::istream& stream) = 0;
+};
+typedef std::shared_ptr<IAasFileLoader> IAasFileLoaderPtr;
+
+// Info structure representing a single AAS file on disk
+struct AasFileInfo
+{
+ std::string absolutePath;
+
+ AasType type;
+};
+
+class IAasFileManager :
+ public RegisterableModule
+{
+public:
+ virtual ~IAasFileManager() {}
+
+ // Register a loader which is considered by all future AAS file load attempts
+ virtual void registerLoader(const IAasFileLoaderPtr& loader) = 0;
+
+ // Unregister a previously registered loader instance
+ virtual void unregisterLoader(const IAasFileLoaderPtr& loader) = 0;
+
+ // Get a loader capable of loading the given stream
+ virtual IAasFileLoaderPtr getLoaderForStream(std::istream& stream) = 0;
+
+ // Get the list of valid AAS types
+ virtual AasTypeList getAasTypes() = 0;
+
+ // Returns a specific AAS type. Will throw a std::runtime_error if the
+ // type is not valid.
+ virtual AasType getAasTypeByName(const std::string& typeName) = 0;
+
+ // Returns a list of AAS files for the given map (absolute) map path
+ virtual std::list<AasFileInfo> getAasFilesForMap(const std::string& mapPath) = 0;
+};
+
+} // namespace
+
+const char* const MODULE_AASFILEMANAGER("ZAasFileManager");
+
+// Application-wide Accessor to the global AAS file manager
+inline map::IAasFileManager& GlobalAasFileManager()
+{
+ // Cache the reference locally
+ static map::IAasFileManager& _manager(
+ *std::static_pointer_cast<map::IAasFileManager>(
+ module::GlobalModuleRegistry().getModule(MODULE_AASFILEMANAGER))
+ );
+ return _manager;
+}
diff --git a/include/icameraview.h b/include/icameraview.h
index dfd1e92..7cff703 100644
--- a/include/icameraview.h
+++ b/include/icameraview.h
@@ -1,6 +1,7 @@
#pragma once
#include "iinteractiveview.h"
+#include "math/Vector3.h"
// Abstract class used when handling mouse events
// see also: class IOrthoView in iorthoview.h
@@ -10,6 +11,17 @@ class ICameraView :
public:
virtual ~ICameraView() {}
+ // Move the camera's origin
+ virtual Vector3 getCameraOrigin() const = 0;
+ virtual void setCameraOrigin(const Vector3& newOrigin) = 0;
+
+ // Returns the vector pointing to the "right"
+ virtual Vector3 getRightVector() const = 0;
+ // Returns the vector pointing "up"
+ virtual Vector3 getUpVector() const = 0;
+ // Returns the vector pointing "forward"
+ virtual Vector3 getForwardVector() const = 0;
+
// Freemove mode
virtual void enableFreeMove() = 0;
virtual void disableFreeMove() = 0;
diff --git a/include/ientity.h b/include/ientity.h
index af2e326..6ebbd0c 100644
--- a/include/ientity.h
+++ b/include/ientity.h
@@ -184,7 +184,13 @@ public:
*/
virtual bool isModel() const = 0;
- virtual bool isContainer() const = 0;
+ /**
+ * Returns true if this entity is the worldspawn, which can be game-specific,
+ * but is usually true if this entity's classname equals "worldspawn"
+ */
+ virtual bool isWorldspawn() const = 0;
+
+ virtual bool isContainer() const = 0;
/**
* \brief
diff --git a/include/ientityinspector.h b/include/ientityinspector.h
index dfd71f6..d1456bd 100644
--- a/include/ientityinspector.h
+++ b/include/ientityinspector.h
@@ -43,6 +43,11 @@ public:
virtual wxPanel* getWidget() = 0;
/**
+ * Instructs the editor to update its widgets from the edited entity's key values.
+ */
+ virtual void updateFromEntity() = 0;
+
+ /**
* Clone method for virtual construction. This method must create a new
* PropertyEditor of the same type as the derive class which is implementing
* the method.
diff --git a/include/igame.h b/include/igame.h
index 62385ac..55129df 100644
--- a/include/igame.h
+++ b/include/igame.h
@@ -55,6 +55,12 @@ class IGameManager :
public RegisterableModule
{
public:
+ // Returns the user's local engine path, on POSIX systems this might
+ // point to the folder in the home directory, e.g. ~/.doom3/ if it exists.
+ // If no engine directory is found in the home directory, the regular
+ // engine path is returned, e.g. /usr/local/doom3 or c:\games\doom3
+ virtual std::string getUserEnginePath() = 0;
+
// Returns the setting for fs_game
virtual const std::string& getFSGame() const = 0;
diff --git a/include/igroupdialog.h b/include/igroupdialog.h
index f34312f..205c317 100644
--- a/include/igroupdialog.h
+++ b/include/igroupdialog.h
@@ -38,9 +38,24 @@ public:
// to be displayed when this tab is active
std::string windowLabel;
- // Optionally specify the name of an already added page to let this page
- // be inserted at a specific point in the tab bar
- std::string insertBefore;
+ // Define the order of the "native" group dialog pages
+ // Use this enum values to indicate which tab position
+ // you need your page to have sorted at
+ struct Position
+ {
+ enum PredefinedValues
+ {
+ EntityInspector = 100,
+ MediaBrowser = 200,
+ Console = 300,
+ TextureBrowser = 400,
+ End = 5000
+ };
+ };
+
+ // Defines the position page in the group dialog (defaults to "End")
+ // See the predefined Position enum for already existing positions
+ int position = Position::End;
};
typedef std::shared_ptr<Page> PagePtr;
diff --git a/include/imap.h b/include/imap.h
index de05d11..62da416 100644
--- a/include/imap.h
+++ b/include/imap.h
@@ -2,6 +2,7 @@
#include "imodule.h"
#include "inode.h"
+#include <sigc++/signal.h>
// Registry setting for suppressing the map load progress dialog
const char* const RKEY_MAP_SUPPRESS_LOAD_STATUS_DIALOG = "user/ui/map/suppressMapLoadDialog";
@@ -59,12 +60,33 @@ class IMap :
public RegisterableModule
{
public:
+ enum MapEvent
+ {
+ MapLoading, // emitted just before a map is starting to be loaded
+ MapLoaded, // emitted when the current map is done loading
+ MapUnloading, // emitted just before a map is unloaded from memory
+ MapUnloaded, // emitted after a map has been unloaded
+ };
+
+ typedef sigc::signal<void, MapEvent> MapEventSignal;
+
+ /// Returns the signal that is emitted on various events
+ virtual MapEventSignal signal_mapEvent() const = 0;
+
/**
* Returns the worldspawn node of this map. The worldspawn
* node is NOT created if it doesn't exist yet, so this
* might return an empty pointer.
*/
- virtual scene::INodePtr getWorldspawn() = 0;
+ virtual const scene::INodePtr& getWorldspawn() = 0;
+
+ /**
+ * This retrieves the worldspawn node of this map.
+ * If no worldspawn can be found, this creates one.
+ * Use this instead of getWorldSpawn() if your code needs
+ * a worldspawn to work with.
+ */
+ virtual const scene::INodePtr& findOrInsertWorldspawn() = 0;
/**
* Returns the root node of this map or NULL if this is an empty map.
diff --git a/include/imapinfofile.h b/include/imapinfofile.h
new file mode 100644
index 0000000..1b961db
--- /dev/null
+++ b/include/imapinfofile.h
@@ -0,0 +1,157 @@
+#pragma once
+
+#include <string>
+#include <map>
+#include "imodule.h"
+#include "imap.h"
+#include <functional>
+
+namespace parser { class DefTokeniser; }
+namespace scene { class INode; typedef std::shared_ptr<INode> INodePtr; }
+
+namespace map
+{
+
+typedef std::pair<std::size_t, std::size_t> NodeIndexPair;
+typedef std::map<NodeIndexPair, scene::INodePtr> NodeIndexMap;
+
+/**
+ * An info file module is allowed to write text-based information
+ * to the auxiliary .darkradiant file that is written alongside to the
+ * game-compatible .map file. Things like layer or selection set/group
+ * information can be stored persistently between mapping sessions this way.
+ *
+ * The module should write its information in named blocks, like
+ *
+ * MyModuleInfo
+ * {
+ * // arbitrary parseable info here
+ * }
+ *
+ * Later, when the info file is parsed after map load, the module will be asked
+ * to parse the blocks it's responsible for, and apply its information to the map.
+ */
+class IMapInfoFileModule
+{
+public:
+ virtual ~IMapInfoFileModule() {}
+
+ // Info File Saving / Exporting
+
+ // The name of this info file module, mainly for internal book-keeping
+ virtual std::string getName() = 0;
+
+ /**
+ * Called before any node is written to the .map file. Use tihs
+ * to prepare the internal structures for exporting.
+ */
+ virtual void onInfoFileSaveStart() = 0;
+
+ /**
+ * Called during map export traversal when a single
+ * primitive is about to be written to the .map file.
+ * Assemble information about the primitive and save it
+ * internally, until the writeBlocks() method is called.
+ */
+ virtual void onSavePrimitive(const scene::INodePtr& node,
+ std::size_t entityNum, std::size_t primitiveNum) = 0;
+
+ /**
+ * Called during map export traversal when a single
+ * entity is about to be written to the .map file.
+ * Assemble information about the entity and save it
+ * internally, until the writeBlocks() method is called.
+ */
+ virtual void onSaveEntity(const scene::INodePtr& node, std::size_t entityNum) = 0;
+
+ /**
+ * Final export function, write the assembled data to the
+ * info file stream. This method should include the block file name
+ * and the opening and closing braces in its write operation.
+ */
+ virtual void writeBlocks(std::ostream& stream) = 0;
+
+ /**
+ * Called before the info file stream is closed, time for cleanup.
+ */
+ virtual void onInfoFileSaveFinished() = 0;
+
+ // Info File Loading / Parsing
+
+ /**
+ * Called before the info file is loaded, so take tihs opportunity to
+ * clear internal structures that are going to be filled during the parse process.
+ */
+ virtual void onInfoFileLoadStart() = 0;
+
+ /**
+ * The info file parser will ask this module when a named block is encountered.
+ * A module which returns true on a block will sign up for parsing the block
+ * and a subsequent call to parseBlock() is imminent.
+ */
+ virtual bool canParseBlock(const std::string& blockName) = 0;
+
+ /**
+ * Parse a block as found in the info file. The block name as passed to this method
+ * needs to be registered in the IMapInfoFileManager class before.
+ *
+ * Regarding the state of the tokeniser: the block name will already have been parsed
+ * by the time this method is called, so expect the opening brace { as first token.
+ */
+ virtual void parseBlock(const std::string& blockName, parser::DefTokeniser& tok) = 0;
+
+ /**
+ * Invoked by the map parsing code when the info file has been fully loaded,
+ * so modules should now apply the loaded information to the map.
+ * The info file is always loaded after the actual .map file, so this method
+ * can assume that the scene graph is already in place.
+ * For convenience, a NodeMap is passed to this method, mapping
+ * the entity/primitive number combination to scene::INodes.
+ */
+ virtual void applyInfoToScene(const scene::IMapRootNodePtr& root, const NodeIndexMap& nodeMap) = 0;
+
+ /**
+ * Post-parsing cleanup routine, called after applyInfoToScene().
+ */
+ virtual void onInfoFileLoadFinished() = 0;
+};
+typedef std::shared_ptr<IMapInfoFileModule> IMapInfoFileModulePtr;
+
+class IMapInfoFileManager :
+ public RegisterableModule
+{
+public:
+ virtual ~IMapInfoFileManager()
+ {}
+
+ /**
+ * Add an info file module to the global list. The module will be considered
+ * during info file export/import.
+ */
+ virtual void registerInfoFileModule(const IMapInfoFileModulePtr& module) = 0;
+
+ /**
+ * Unregister a previouly registered info file module.
+ */
+ virtual void unregisterInfoFileModule(const IMapInfoFileModulePtr& module) = 0;
+
+ /**
+ * Call the functor for each registered module.
+ */
+ virtual void foreachModule(const std::function<void(IMapInfoFileModule&)>& functor) = 0;
+};
+
+}
+
+const char* const MODULE_MAPINFOFILEMANAGER("MapInfoFileManager");
+
+// Application-wide Accessor to the global map info file manager
+inline map::IMapInfoFileManager& GlobalMapInfoFileManager()
+{
+ // Cache the reference locally
+ static map::IMapInfoFileManager& _manager(
+ *std::static_pointer_cast<map::IMapInfoFileManager>(
+ module::GlobalModuleRegistry().getModule(MODULE_MAPINFOFILEMANAGER))
+ );
+ return _manager;
+}
diff --git a/include/imapresource.h b/include/imapresource.h
index 663edb5..3e75f91 100644
--- a/include/imapresource.h
+++ b/include/imapresource.h
@@ -13,45 +13,40 @@ namespace map
class IMapResource
{
public:
- class Observer {
- public:
- virtual ~Observer() {}
- virtual void onResourceRealise() = 0;
- virtual void onResourceUnrealise() = 0;
- };
-
virtual ~IMapResource() {}
// Renames this map resource to the new path
virtual void rename(const std::string& fullPath) = 0;
virtual bool load() = 0;
- virtual bool save(const map::MapFormatPtr& mapFormat = map::MapFormatPtr()) = 0;
- // Reloads the map file from disk
- virtual void reload() = 0;
+ /**
+ * Save this resource
+ *
+ * It's possible to pass a mapformat to be used for saving. If the map
+ * format argument is omitted, the format corresponding to the current
+ * game type is used.
+ *
+ * @returns
+ * true if the resource was saved, false otherwise.
+ */
+ virtual bool save(const map::MapFormatPtr& mapFormat = map::MapFormatPtr()) = 0;
virtual scene::IMapRootNodePtr getNode() = 0;
virtual void setNode(const scene::IMapRootNodePtr& node) = 0;
-
- virtual void addObserver(Observer& observer) = 0;
- virtual void removeObserver(Observer& observer) = 0;
-
- virtual void realise() = 0;
- virtual void unrealise() = 0;
};
typedef std::shared_ptr<IMapResource> IMapResourcePtr;
-const std::string MODULE_MAPRESOURCEMANAGER("MapResourceManager");
+const char* const MODULE_MAPRESOURCEMANAGER("MapResourceManager");
class IMapResourceManager :
public RegisterableModule
{
public:
/**
- * Capture a named model resource, and return a pointer to it.
+ * Load the named map resource from VFS or from a physical path.
*/
- virtual IMapResourcePtr capture(const std::string& path) = 0;
+ virtual IMapResourcePtr loadFromPath(const std::string& path) = 0;
};
inline IMapResourceManager& GlobalMapResourceManager() {
diff --git a/include/inode.h b/include/inode.h
index da8a5a6..b87dd98 100644
--- a/include/inode.h
+++ b/include/inode.h
@@ -145,8 +145,20 @@ public:
*/
virtual bool excluded() const = 0;
+ // Set the "forced visible" flag, which overrides the ordinary filtered/excluded state
+ // This is used to force the rendering of nodes that are selected but would otherwise
+ // be hidden due to the filtered/layered state.
+ virtual void setForcedVisibility(bool forceVisible, bool includeChildren) = 0;
+
// Child node handling
+
+ // Adds a new child node (is appended at the end of the list of existing children)
virtual void addChildNode(const INodePtr& node) = 0;
+
+ // Adds a new child node (is inserted at the front of any existing children)
+ // Useful in special scenarios like when adding a world spawn node.
+ virtual void addChildNodeToFront(const INodePtr& node) = 0;
+
virtual void removeChildNode(const INodePtr& node) = 0;
virtual bool hasChildNodes() const = 0;
diff --git a/include/iorthocontextmenu.h b/include/iorthocontextmenu.h
index fedb5a7..fd0a3dc 100644
--- a/include/iorthocontextmenu.h
+++ b/include/iorthocontextmenu.h
@@ -16,6 +16,7 @@ public:
{
SECTION_CREATE, // Create Entity, Create Speaker, etc.
SECTION_ACTION, // Make Visportals
+ SECTION_SELECTION_GROUPS, // Selection Groups
SECTION_LAYER, // Layer operations
SECTION_USER = 100,
};
diff --git a/include/ipatch.h b/include/ipatch.h
index 70658df..9b5eb52 100644
--- a/include/ipatch.h
+++ b/include/ipatch.h
@@ -154,11 +154,11 @@ public:
/**
* greebo: Sets/gets whether this patch is a patchDef3 (fixed tesselation)
*/
- virtual bool subdivionsFixed() const = 0;
+ virtual bool subdivisionsFixed() const = 0;
/** greebo: Returns the x,y subdivision values (for tesselation)
*/
- virtual Subdivisions getSubdivisions() const = 0;
+ virtual const Subdivisions& getSubdivisions() const = 0;
/** greebo: Sets the subdivision of this patch
*
diff --git a/include/ipreferencesystem.h b/include/ipreferencesystem.h
index facb035..07610ae 100644
--- a/include/ipreferencesystem.h
+++ b/include/ipreferencesystem.h
@@ -1,38 +1,34 @@
#pragma once
#include <list>
-#include <vector>
#include "imodule.h"
// A list containing possible values for a combo box widgets
typedef std::list<std::string> ComboBoxValueList;
-typedef std::vector<std::string> IconList;
-typedef std::vector<std::string> IconDescriptionList;
/* greebo: This is the interface the preference page has to provide for adding
* elements to the dialog page. */
-class PreferencesPage
+class IPreferencePage
{
public:
// destructor
- virtual ~PreferencesPage() {}
+ virtual ~IPreferencePage() {}
- /** greebo: Allows to set a custom title of this page. The default title
- * upon construction is "guessed" by adding a " Settings" to
- * the page name, "Settings/Patch" gets assigned
- * a "Patch Settings" as default title.
- * Use this method to change this to fit your needs.
+ /**
+ * greebo: Allows to set a custom title of this page. The default title
+ * upon construction is "guessed" by adding a " Settings" to
+ * the page name, "Settings/Patch" gets assigned
+ * a "Patch Settings" as default title.
+ * Use this method to change this to fit your needs.
*/
virtual void setTitle(const std::string& title) = 0;
// greebo: Use this to add a checkbox to the preference dialog that is connected to a registry value
- virtual void appendCheckBox(const std::string& name, const std::string& flag, const std::string& registryKey) = 0;
+ virtual void appendCheckBox(const std::string& label, const std::string& registryKey) = 0;
- /* greebo: This adds a horizontal slider to the internally referenced VBox and connects
- * it to the given registryKey. */
- virtual void appendSlider(const std::string& name, const std::string& registryKey, bool drawValue,
- double value, double lower, double upper,
- double step_increment, double page_increment, double page_size) = 0;
+ // greebo: This adds a horizontal slider and connects it to the given registryKey.
+ virtual void appendSlider(const std::string& name, const std::string& registryKey,
+ double lower, double upper, double step_increment, double page_increment) = 0;
/**
* \brief
@@ -76,30 +72,30 @@ public:
// Appends a static label (to add some text to the preference page)
virtual void appendLabel(const std::string& caption) = 0;
};
-typedef std::shared_ptr<PreferencesPage> PreferencesPagePtr;
-const std::string MODULE_PREFERENCESYSTEM("PreferenceSystem");
+const char* const MODULE_PREFERENCESYSTEM("PreferenceSystem");
class IPreferenceSystem :
public RegisterableModule
{
public:
- /** greebo: Retrieves the page for the given path, for example:
+ /**
+ * greebo: Retrieves the page for the given path. If the page
+ * doesn't exist yet, it will be created at the given path, for example:
*
- * "Settings/Patch Settings"
- * (spaces are ok, slashes are treated as delimiters, don't use them)
+ * "Settings/Patch Settings"
+ * (spaces are ok, slashes are treated as delimiters, don't use them in the page name)
*
- * Use the PreferencesPage interface to add widgets
- * and connect them to the registry.
- *
- * @path: The path to lookup
- *
- * @returns: the PreferencesPage pointer.
+ * Use the page interface to add widgets and connect them to registry keys.
+
+ * @path: The path to lookup/create
+ * @returns: the IPreferencePage reference.
*/
- virtual PreferencesPagePtr getPage(const std::string& path) = 0;
+ virtual IPreferencePage& getPage(const std::string& path) = 0;
};
-inline IPreferenceSystem& GlobalPreferenceSystem() {
+inline IPreferenceSystem& GlobalPreferenceSystem()
+{
// Cache the reference locally
static IPreferenceSystem& _prefSystem(
*std::static_pointer_cast<IPreferenceSystem>(
diff --git a/include/irenderable.h b/include/irenderable.h
index 082b539..bc53266 100644
--- a/include/irenderable.h
+++ b/include/irenderable.h
@@ -106,11 +106,18 @@ public:
*/
virtual bool supportsFullMaterials() const = 0;
- /// Highlight faces of subsequently-submitted objects, if supported
- virtual void highlightFaces(bool enable) = 0;
+ struct Highlight
+ {
+ enum Flags
+ {
+ NoHighlight = 0,
+ Faces = 1 << 0, /// Highlight faces of subsequently-submitted objects, if supported
+ Primitives = 1 << 1, /// Highlight primitives of subsequently-submitted objects, if supported
+ GroupMember = 1 << 2, /// Highlight as member of group, if supported
+ };
+ };
- /// Highlight primitives of subsequently-submitted objects, if supported
- virtual void highlightPrimitives(bool enable) = 0;
+ virtual void setHighlightFlag(Highlight::Flags flags, bool enabled) = 0;
/**
* Set the list of lights to be used for lighting-mode rendering. This
@@ -161,10 +168,19 @@ public:
virtual void viewChanged() const
{ }
+ struct Highlight
+ {
+ enum Flags
+ {
+ NoHighlight = 0,
+ Selected = 1 << 0,
+ GroupMember = 1 << 1,
+ };
+ };
+
/**
- * Method to determine whether this node should be rendered as highlighted.
- * This is usually true for selected nodes.
+ * Returns information about whether the renderer should highlight this node and how.
*/
- virtual bool isHighlighted() const = 0;
+ virtual std::size_t getHighlightFlags() = 0;
};
typedef std::shared_ptr<Renderable> RenderablePtr;
diff --git a/include/iselectable.h b/include/iselectable.h
index aada844..a70aef1 100644
--- a/include/iselectable.h
+++ b/include/iselectable.h
@@ -1,25 +1,24 @@
#pragma once
+#include <memory>
+
/**
* greebo: A Selectable is everything that can be highlighted
- * by the user in the scene (e.g. by interaction with the mouse).
+ * by the user in the scene (e.g. by interaction with the mouse).
*/
-class Selectable
+class ISelectable
{
public:
// destructor
- virtual ~Selectable() {}
+ virtual ~ISelectable() {}
// Set the selection status of this object
virtual void setSelected(bool select) = 0;
// Check the selection status of this object (TRUE == selected)
virtual bool isSelected() const = 0;
-
- // Toggle the selection status
- virtual void invertSelected() = 0;
};
-typedef std::shared_ptr<Selectable> SelectablePtr;
+typedef std::shared_ptr<ISelectable> ISelectablePtr;
namespace scene
{
@@ -27,14 +26,14 @@ namespace scene
typedef std::shared_ptr<INode> INodePtr;
}
-inline SelectablePtr Node_getSelectable(const scene::INodePtr& node)
+inline ISelectablePtr Node_getSelectable(const scene::INodePtr& node)
{
- return std::dynamic_pointer_cast<Selectable>(node);
+ return std::dynamic_pointer_cast<ISelectable>(node);
}
inline void Node_setSelected(const scene::INodePtr& node, bool selected)
{
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
if (selectable)
{
@@ -44,7 +43,7 @@ inline void Node_setSelected(const scene::INodePtr& node, bool selected)
inline bool Node_isSelected(const scene::INodePtr& node)
{
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
if (selectable)
{
diff --git a/include/iselection.h b/include/iselection.h
index 50bdb21..cc41c57 100644
--- a/include/iselection.h
+++ b/include/iselection.h
@@ -8,7 +8,7 @@
class RenderableCollector;
namespace render { class View; }
-class Selectable;
+class ISelectable;
namespace scene
@@ -26,8 +26,8 @@ typedef BasicVector4<double> Vector4;
class Matrix4;
class Quaternion;
-typedef sigc::signal<void, const Selectable&> SelectionChangedSignal;
-typedef sigc::slot<void, const Selectable&> SelectionChangedSlot;
+typedef sigc::signal<void, const ISelectable&> SelectionChangedSignal;
+typedef sigc::slot<void, const ISelectable&> SelectionChangedSlot;
class SelectionInfo;
class Face;
@@ -103,8 +103,8 @@ public:
virtual std::size_t countSelected() const = 0;
virtual std::size_t countSelectedComponents() const = 0;
- virtual void onSelectedChanged(const scene::INodePtr& node, const Selectable& selectable) = 0;
- virtual void onComponentSelection(const scene::INodePtr& node, const Selectable& selectable) = 0;
+ virtual void onSelectedChanged(const scene::INodePtr& node, const ISelectable& selectable) = 0;
+ virtual void onComponentSelection(const scene::INodePtr& node, const ISelectable& selectable) = 0;
virtual scene::INodePtr ultimateSelected() = 0;
virtual scene::INodePtr penultimateSelected() = 0;
diff --git a/include/iselectiongroup.h b/include/iselectiongroup.h
new file mode 100644
index 0000000..d70d36d
--- /dev/null
+++ b/include/iselectiongroup.h
@@ -0,0 +1,120 @@
+#pragma once
+
+#include "imodule.h"
+#include "iselectable.h"
+#include <sigc++/signal.h>
+
+// GroupSelectables are regular selectables which can be part of
+// one or more SelectionGroups.
+class IGroupSelectable :
+ public ISelectable
+{
+public:
+ typedef std::vector<std::size_t> GroupIds;
+
+ virtual ~IGroupSelectable() {}
+
+ // Adds this item to the group specified by its ID
+ virtual void addToGroup(std::size_t groupId) = 0;
+
+ // Removes this item from the group specified by its ID
+ virtual void removeFromGroup(std::size_t groupId) = 0;
+
+ // Returns true if this node is member of any group
+ virtual bool isGroupMember() = 0;
+
+ // Returns the group this node has been added to last
+ // This represents the currently "active" group ID
+ // Will throw an exception if this node is not a member of any group
+ virtual std::size_t getMostRecentGroupId() = 0;
+
+ // Returns all group assignments of this node
+ // The most recently added group is at the back of the list
+ virtual const GroupIds& getGroupIds() = 0;
+
+ // Special overload to control whether this selectable should propagate
+ // the status change to the group it belongs to.
+ virtual void setSelected(bool select, bool changeGroupStatus) = 0;
+};
+
+namespace selection
+{
+
+// Represents a SelectionGroup which can contain 0 or more IGroupSelectable nodes.
+class ISelectionGroup
+{
+public:
+ virtual ~ISelectionGroup() {}
+
+ // Returns the ID of this group
+ virtual std::size_t getId() const = 0;
+
+ // Gets the name of this group
+ virtual const std::string& getName() const = 0;
+
+ // Sets the name of this group
+ virtual void setName(const std::string& name) = 0;
+
+ // Adds the given node to this group. The node should be a IGroupSelectable
+ // which will be checked internally. If the node is not matching, nothing happens.
+ virtual void addNode(const scene::INodePtr& node) = 0;
+
+ // Remvoes the given node from this group. The node should be a IGroupSelectable
+ // which will be checked internally. If the node is not matching, nothing happens.
+ // The group will not be removed if this was the last member node
+ virtual void removeNode(const scene::INodePtr& node) = 0;
+
+ // Returns the number of nodes in this group
+ virtual std::size_t size() const = 0;
+
+ // Sets the selection status of all the nodes in this group
+ virtual void setSelected(bool selected) = 0;
+
+ // Calls the given functor for each node in this group.
+ // The functor should not change the membership of this group, this will likely lead
+ // to internal iterator corruption.
+ virtual void foreachNode(const std::function<void(const scene::INodePtr&)>& functor) = 0;
+};
+typedef std::shared_ptr<ISelectionGroup> ISelectionGroupPtr;
+
+class ISelectionGroupManager :
+ public RegisterableModule
+{
+public:
+ virtual ~ISelectionGroupManager() {}
+
+ // Creates a new selection group. The group is stored within the SelectionGroupManager
+ // so the returned shared_ptr can safely be let go by the client code.
+ // In the pathological case of being run out of IDs this will throw a std::runtime_error
+ virtual ISelectionGroupPtr createSelectionGroup() = 0;
+
+ // Tries to get a selection group by ID. Returns an empty ptr if the ID doesn't exist
+ virtual ISelectionGroupPtr getSelectionGroup(std::size_t id) = 0;
+
+ // Unline getSelectionGroup() this will create the group if it doesn't exist
+ virtual ISelectionGroupPtr findOrCreateSelectionGroup(std::size_t id) = 0;
+
+ // Sets the selection status of all members of the given group
+ virtual void setGroupSelected(std::size_t id, bool selected) = 0;
+
+ // Deletes all selection groups
+ virtual void deleteAllSelectionGroups() = 0;
+
+ // Deletes the group with the given ID. All nodes will be removed from this group as well.
+ virtual void deleteSelectionGroup(std::size_t id) = 0;
+};
+
+} // namespace
+
+const char* const MODULE_SELECTIONGROUP = "SelectionGroupManager";
+
+inline selection::ISelectionGroupManager& GlobalSelectionGroupManager()
+{
+ // Cache the reference locally
+ static selection::ISelectionGroupManager& _manager(
+ *std::static_pointer_cast<selection::ISelectionGroupManager>(
+ module::GlobalModuleRegistry().getModule(MODULE_SELECTIONGROUP)
+ )
+ );
+ return _manager;
+}
diff --git a/include/iselectiontest.h b/include/iselectiontest.h
index 9bdc0bb..48f40f3 100644
--- a/include/iselectiontest.h
+++ b/include/iselectiontest.h
@@ -234,19 +234,19 @@ class Selector
{
public:
virtual ~Selector() {}
- virtual void pushSelectable(Selectable& selectable) = 0;
+ virtual void pushSelectable(ISelectable& selectable) = 0;
virtual void popSelectable() = 0;
virtual void addIntersection(const SelectionIntersection& intersection) = 0;
};
-inline void Selector_add(Selector& selector, Selectable& selectable)
+inline void Selector_add(Selector& selector, ISelectable& selectable)
{
selector.pushSelectable(selectable);
selector.addIntersection(SelectionIntersection(0, 0));
selector.popSelectable();
}
-inline void Selector_add(Selector& selector, Selectable& selectable, const SelectionIntersection& intersection)
+inline void Selector_add(Selector& selector, ISelectable& selectable, const SelectionIntersection& intersection)
{
selector.pushSelectable(selectable);
selector.addIntersection(intersection);
@@ -271,6 +271,7 @@ public:
virtual ~ComponentSelectionTestable() {}
virtual bool isSelectedComponents() const = 0;
virtual void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) = 0;
+ virtual void invertSelectedComponents(SelectionSystem::EComponentMode mode) = 0;
virtual void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) = 0;
};
typedef std::shared_ptr<ComponentSelectionTestable> ComponentSelectionTestablePtr;
diff --git a/include/iuimanager.h b/include/iuimanager.h
index 0fdb3bb..196a793 100644
--- a/include/iuimanager.h
+++ b/include/iuimanager.h
@@ -159,8 +159,10 @@ public:
* if no icon is desired.
* @pos: the position to insert. Use POS_FRONT or POS_BACK to put the element
* at the front or back of the status bar container.
+ * @description: a description shown when the mouse pointer hovers of this item.
*/
- virtual void addTextElement(const std::string& name, const std::string& icon, int pos) = 0;
+ virtual void addTextElement(const std::string& name, const std::string& icon, int pos,
+ const std::string& description) = 0;
/**
* Updates the content of the named text element. The name must refer to
diff --git a/include/precompiled_interfaces.h b/include/precompiled_interfaces.h
index fad4093..6cbe544 100644
--- a/include/precompiled_interfaces.h
+++ b/include/precompiled_interfaces.h
@@ -45,6 +45,7 @@
#include "imainframelayout.h"
#include "imap.h"
#include "imapformat.h"
+#include "imapinfofile.h"
//#include "imapcompiler.h"
#include "imapresource.h"
#include "imd5anim.h"
@@ -78,6 +79,7 @@
#include "iscript.h"
#include "iselectable.h"
#include "iselection.h"
+#include "iselectiongroup.h"
#include "iselectionset.h"
#include "iselectiontest.h"
#include "ishaderexpression.h"
diff --git a/include/version.h b/include/version.h
index fe36bf6..639eefa 100644
--- a/include/version.h
+++ b/include/version.h
@@ -2,7 +2,7 @@
#include <config.h>
#define RADIANT_VERSION PACKAGE_VERSION
#else
-#define RADIANT_VERSION "2.0.4"
+#define RADIANT_VERSION "2.1.0"
#endif
#define RADIANT_APPNAME "DarkRadiant"
diff --git a/install/bitmaps/empty.png b/install/bitmaps/empty.png
index c5fbfa2..c400b22 100644
Binary files a/install/bitmaps/empty.png and b/install/bitmaps/empty.png differ
diff --git a/install/bitmaps/group_selection.png b/install/bitmaps/group_selection.png
new file mode 100644
index 0000000..b6b98d5
Binary files /dev/null and b/install/bitmaps/group_selection.png differ
diff --git a/install/bitmaps/ungroup_selection.png b/install/bitmaps/ungroup_selection.png
new file mode 100644
index 0000000..7a51274
Binary files /dev/null and b/install/bitmaps/ungroup_selection.png differ
diff --git a/install/i18n/darkradiant.pot b/install/i18n/darkradiant.pot
index b55290c..9f99a86 100644
--- a/install/i18n/darkradiant.pot
+++ b/install/i18n/darkradiant.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: greebo at angua.at\n"
-"POT-Creation-Date: 2016-01-05 11:54+0100\n"
+"POT-Creation-Date: 2016-11-18 18:32+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at li.org>\n"
@@ -79,11 +79,11 @@ msgstr ""
msgid "Solid selection boxes"
msgstr ""
-#: ..\..\radiant\camera\CameraSettings.cpp:75
+#: ..\..\radiant\camera\CameraSettings.cpp:74
msgid "Show camera toolbar"
msgstr ""
-#: ..\..\radiant\camera\FloatingCamWnd.cpp:18 xml_file_content.cpp:60
+#: ..\..\radiant\camera\FloatingCamWnd.cpp:18 xml_file_content.cpp:61
msgid "Camera"
msgstr ""
@@ -95,27 +95,31 @@ msgstr ""
msgid "Jump to Object"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:97
+#: ..\..\radiant\camera\tools\PanViewTool.h:23
+msgid "Pan Camera View"
+msgstr ""
+
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:116
msgid "Pick Shader"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:120
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:139
msgid "Paste Shader Projected"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:138
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:158
msgid "Paste Shader Natural"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:156
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:177
msgid "Paste Texture Coordinates"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:174
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:196
msgid "Paste Shader to all Brush Faces"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:192
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:215
msgid "Paste Shader Name"
msgstr ""
@@ -131,40 +135,40 @@ msgstr ""
msgid "Caulk shader name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:34
+#: ..\..\radiant\layers\LayerSystem.cpp:36
msgid "Default"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:37
+#: ..\..\radiant\layers\LayerSystem.cpp:39
msgid "Create Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:39
+#: ..\..\radiant\layers\LayerSystem.cpp:41
msgid "Add to Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:40
+#: ..\..\radiant\layers\LayerSystem.cpp:42
msgid "Move to Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:41
+#: ..\..\radiant\layers\LayerSystem.cpp:43
msgid "Remove from Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:536
+#: ..\..\radiant\layers\LayerSystem.cpp:550
#: ..\..\plugins\particles\editor\ParticleEditor.cpp:1537
msgid "Enter Name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:537
+#: ..\..\radiant\layers\LayerSystem.cpp:551
msgid "Enter Layer Name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:549
+#: ..\..\radiant\layers\LayerSystem.cpp:563
msgid "Cannot create layer with empty name."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:563
+#: ..\..\radiant\layers\LayerSystem.cpp:577
msgid "This name already exists."
msgstr ""
@@ -195,33 +199,39 @@ msgstr ""
msgid "Loading entity %d\n"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:299
+#: ..\..\radiant\map\AutoSaver.cpp:276
msgid "Settings/Autosave"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:302
+#: ..\..\radiant\map\AutoSaver.cpp:279
msgid "Enable Autosave"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:303
+#: ..\..\radiant\map\AutoSaver.cpp:280
msgid "Autosave Interval (in minutes)"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:305
+#: ..\..\radiant\map\AutoSaver.cpp:282
msgid "Save Snapshots"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:306
+#: ..\..\radiant\map\AutoSaver.cpp:283
msgid "Snapshot folder (relative to map folder)"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:307
+#: ..\..\radiant\map\AutoSaver.cpp:284
msgid "Max Snapshot Folder size (MB)"
msgstr ""
-#: ..\..\radiant\map\CounterManager.cpp:67
+#: ..\..\radiant\map\CounterManager.cpp:63
+msgid ""
+"Number of brushes/patches/entities in this map\n"
+"(Number of selected items shown in parentheses)"
+msgstr ""
+
+#: ..\..\radiant\map\CounterManager.cpp:81
#, c-format
-msgid "Brushes: %lu Patches: %lu Entities: %lu"
+msgid "Brushes: %lu (%lu) Patches: %lu (%lu) Entities: %lu (%lu)"
msgstr ""
#: ..\..\radiant\map\FindMapElements.cpp:95
@@ -236,92 +246,92 @@ msgstr ""
msgid "Brush Number:"
msgstr ""
-#: ..\..\radiant\map\InfoFile.cpp:73
+#: ..\..\radiant\map\infofile\InfoFile.cpp:70
msgid "Map Info File Version invalid"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:59
+#: ..\..\radiant\map\Map.cpp:62
msgid "unnamed.map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:182 ..\..\radiant\map\Map.cpp:518
-#: ..\..\radiant\map\Map.cpp:610 ..\..\radiant\map\Map.cpp:638
-#: ..\..\radiant\RadiantModule.cpp:134
+#: ..\..\radiant\map\Map.cpp:106 ..\..\radiant\map\Map.cpp:431
+#: ..\..\radiant\map\Map.cpp:522 ..\..\radiant\map\Map.cpp:550
+#: ..\..\radiant\RadiantModule.cpp:135
#: ..\..\radiant\referencecache\ModelCache.cpp:245
#: ..\..\radiant\referencecache\ModelCache.cpp:261
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Processing..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:182
+#: ..\..\radiant\map\Map.cpp:106
msgid "Loading textures..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:518
+#: ..\..\radiant\map\Map.cpp:431
msgid "Saving Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:569
+#: ..\..\radiant\map\Map.cpp:481
msgid "Importing..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:664
+#: ..\..\radiant\map\Map.cpp:576
#, c-format
msgid ""
"Save changes to map \"%s\"\n"
"before closing?"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:672
+#: ..\..\radiant\map\Map.cpp:584
#, c-format
msgid "%d minutes"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:676
+#: ..\..\radiant\map\Map.cpp:588
#, c-format
msgid "%d seconds"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:680
+#: ..\..\radiant\map\Map.cpp:592
#, c-format
msgid ""
"If you don't save, changes from the last %s\n"
"will be lost."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:738
+#: ..\..\radiant\map\Map.cpp:650
msgid "Save Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:778
+#: ..\..\radiant\map\Map.cpp:690
msgid "Save Copy As..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:854
+#: ..\..\radiant\map\Map.cpp:781
msgid "New Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:865 ..\..\radiant\ui\mru\MRU.cpp:93
+#: ..\..\radiant\map\Map.cpp:790 ..\..\radiant\ui\mru\MRU.cpp:93
msgid "Open Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:869
+#: ..\..\radiant\map\Map.cpp:794
msgid "Open map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:883
+#: ..\..\radiant\map\Map.cpp:808
msgid "Import map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:912
+#: ..\..\radiant\map\Map.cpp:837
msgid "Export selection"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:927
+#: ..\..\radiant\map\Map.cpp:852
msgid "Save selected as Prefab"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:1008
+#: ..\..\radiant\map\Map.cpp:933
#, c-format
msgid ""
"Failure reading map from clipboard:\n"
@@ -332,39 +342,32 @@ msgstr ""
msgid "Map"
msgstr ""
-#: ..\..\radiant\map\MapFileManager.cpp:36 xml_file_content.cpp:89
+#: ..\..\radiant\map\MapFileManager.cpp:36 xml_file_content.cpp:90
msgid "Region"
msgstr ""
#: ..\..\radiant\map\MapFileManager.cpp:37
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:327
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:343
msgid "Prefab"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:273 ..\..\radiant\map\MapResource.cpp:641
+#: ..\..\radiant\map\MapResource.cpp:257 ..\..\radiant\map\MapResource.cpp:529
#, c-format
msgid "File is write-protected: %s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:434
-#, c-format
-msgid ""
-"Failure opening map file:\n"
-"%s"
-msgstr ""
-
-#: ..\..\radiant\map\MapResource.cpp:476
+#: ..\..\radiant\map\MapResource.cpp:363
#, c-format
msgid ""
"Could not determine map format of file:\n"
"%s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:602
+#: ..\..\radiant\map\MapResource.cpp:410
msgid "Map loading cancelled"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:614
+#: ..\..\radiant\map\MapResource.cpp:422
#, c-format
msgid ""
"Failure reading map file:\n"
@@ -373,40 +376,47 @@ msgid ""
"%s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:706
+#: ..\..\radiant\map\MapResource.cpp:485 ..\..\radiant\map\MapResource.cpp:504
+#, c-format
+msgid ""
+"Failure opening file:\n"
+"%s"
+msgstr ""
+
+#: ..\..\radiant\map\MapResource.cpp:594
msgid "Map writing cancelled"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:721
+#: ..\..\radiant\map\MapResource.cpp:609
msgid "Could not open output streams for writing"
msgstr ""
-#: ..\..\radiant\map\PointFile.cpp:116
+#: ..\..\radiant\map\PointFile.cpp:126
#, c-format
msgid "Could not open pointfile: %s"
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:203
+#: ..\..\radiant\map\RegionManager.cpp:173
msgid "Warning: Camera not within region, can't set info_player_start."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:293
+#: ..\..\radiant\map\RegionManager.cpp:261
msgid "Could not set Region: XY Top View not found."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:320
+#: ..\..\radiant\map\RegionManager.cpp:288
msgid "Could not set Region: please select a single Brush."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:345
+#: ..\..\radiant\map\RegionManager.cpp:313
msgid "This command is not available in component mode."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:351
+#: ..\..\radiant\map\RegionManager.cpp:319
msgid "Could not set Region: nothing selected."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:368
+#: ..\..\radiant\map\RegionManager.cpp:336
msgid "Export region"
msgstr ""
@@ -423,7 +433,7 @@ msgstr ""
msgid "Initialising Modules"
msgstr ""
-#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:165
+#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:162
msgid "Modules initialised"
msgstr ""
@@ -455,7 +465,7 @@ msgstr ""
msgid "Cannot create cylinder-cap, patch must have a width of 9."
msgstr ""
-#: ..\..\radiant\patch\Patch.cpp:1667
+#: ..\..\radiant\patch\Patch.cpp:1639
msgid "Sorry. Patch is not suitable for this kind of operation."
msgstr ""
@@ -471,11 +481,11 @@ msgstr ""
#: ..\..\radiant\settings\GameManager.cpp:97
#: ..\..\radiant\settings\GameManager.cpp:323
#: ..\..\radiant\settings\GameManager.cpp:344
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:198
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:169
msgid "Game"
msgstr ""
-#: ..\..\radiant\RadiantModule.cpp:238
+#: ..\..\radiant\RadiantModule.cpp:239
msgid "Settings"
msgstr ""
@@ -508,41 +518,82 @@ msgstr ""
msgid "Can't convert curves - no entities with curves selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:62
+#: ..\..\radiant\selection\algorithm\Entity.cpp:82
+#, c-format
+msgid "The name %s already exists in this map!"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:106
+msgid "Cannot set classname to an empty string."
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:112
+msgid "Cannot change classname to worldspawn."
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:131
msgid "Cannot change classname of worldspawn entity."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:104
+#: ..\..\radiant\selection\algorithm\Entity.cpp:169
msgid "Critical: Cannot find selected entities."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:109
-#: ..\..\radiant\selection\algorithm\Entity.cpp:125
+#: ..\..\radiant\selection\algorithm\Entity.cpp:174
+#: ..\..\radiant\selection\algorithm\Entity.cpp:190
msgid "Exactly two entities must be selected for this operation."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:171
+#: ..\..\radiant\selection\algorithm\Entity.cpp:236
#, c-format
msgid "Unable to create entity %s, no brushes selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Group.cpp:236
+#: ..\..\radiant\selection\algorithm\Group.cpp:234
msgid ""
"Cannot reparent primitives to entity. Please select at least one brush/patch "
"and exactly one entity.(The entity has to be selected last.)"
msgstr ""
-#: ..\..\radiant\selection\algorithm\Group.cpp:386
+#: ..\..\radiant\selection\algorithm\Group.cpp:384
msgid ""
"Cannot merge entities, the selection must consist of func_* entities only.\n"
"(The first selected entity will be preserved.)"
msgstr ""
+#: ..\..\radiant\selection\algorithm\Group.cpp:394
+msgid "Groups can be formed in Primitive selection mode only"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:399
+msgid "Nothing selected, cannot group anything"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:404
+msgid "Select more than one element to form a group"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:430
+msgid "The selected elements already form a group"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:455
+msgid "Groups can be dissolved in Primitive selection mode only"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:460
+msgid "Nothing selected, cannot un-group anything"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:480
+msgid "The selected elements aren't part of any group"
+msgstr ""
+
#: ..\..\radiant\selection\algorithm\Patch.cpp:60
msgid "Cannot create caps, no patches selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Patch.cpp:208
+#: ..\..\radiant\selection\algorithm\Patch.cpp:197
msgid "Cannot thicken patch. Nothing selected."
msgstr ""
@@ -573,42 +624,52 @@ msgstr ""
msgid "At least one brush must be selected for this operation."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:285
+#: ..\..\radiant\selection\algorithm\Shader.cpp:307
msgid ""
"Can't paste shader to entire brush.\n"
"Target is not a brush."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:320
+#: ..\..\radiant\selection\algorithm\Shader.cpp:346
msgid ""
"Can't paste Texture Coordinates.\n"
"Target patch dimensions must match."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:327
+#: ..\..\radiant\selection\algorithm\Shader.cpp:355
msgid "Can't paste Texture Coordinates from patches to faces."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:332
+#: ..\..\radiant\selection\algorithm\Shader.cpp:361
msgid "Can't paste Texture Coordinates from faces."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:388
+#: ..\..\radiant\selection\algorithm\Shader.cpp:417
msgid "Can't copy Shader. Couldn't retrieve patch."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:398
+#: ..\..\radiant\selection\algorithm\Shader.cpp:427
msgid "Can't copy Shader. Couldn't retrieve face."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:404
+#: ..\..\radiant\selection\algorithm\Shader.cpp:433
msgid "Can't copy Shader. Please select a single face or patch."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Transformation.cpp:55
+#: ..\..\radiant\selection\algorithm\Transformation.cpp:56
msgid "Cannot scale by zero value."
msgstr ""
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:81
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:97
+msgid "Ungroup Selection"
+msgstr ""
+
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:84
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:91
+msgid "Group Selection"
+msgstr ""
+
#: ..\..\radiant\selection\ManipulateMouseTool.cpp:28
msgid "Manipulate"
msgstr ""
@@ -617,31 +678,31 @@ msgstr ""
msgid "Select"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:168 xml_file_content.cpp:4
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:175 xml_file_content.cpp:4
msgid "Select Faces"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:187
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:194
msgid "Cycle Selection"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:233
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:247
msgid "Cycle Face Selection"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:84
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:104
msgid "Selection Set: "
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:92
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:112
msgid "Clear Selection Sets"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:194
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:214
msgid "Delete all selection sets?"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:195
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:215
msgid ""
"This will delete all set definitions. The actual map objects will not be "
"affected by this step.\n"
@@ -669,20 +730,24 @@ msgid ""
"scene."
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:87
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:24
+msgid "The name of the shader in the clipboard"
+msgstr ""
+
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:91
#, c-format
msgid "ShaderClipboard: %s"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:90
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:94
msgid "Face"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:93
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:97
msgid "Patch"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:96
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
#: ..\..\radiant\ui\common\ShaderSelector.cpp:359
#: ..\..\radiant\ui\common\TexturePreviewCombo.cpp:73
#: ..\..\radiant\ui\mapinfo\ShaderInfoTab.cpp:60
@@ -690,7 +755,7 @@ msgstr ""
msgid "Shader"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:104
msgid "ShaderClipboard is empty."
msgstr ""
@@ -1487,10 +1552,35 @@ msgstr ""
msgid "Zulu"
msgstr ""
+#: ..\..\radiant\settings\PreferencePage.cpp:19
+#, c-format
+msgid "%s Settings"
+msgstr ""
+
#: ..\..\radiant\textool\TexTool.cpp:38
msgid "Texture Tool"
msgstr ""
+#: ..\..\radiant\ui\aas\AasControl.cpp:36
+msgid "Reload AAS File"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:30
+msgid "AAS Viewer"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:80
+msgid "Search for AAS Files"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:84
+msgid "Show Area Numbers"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:87
+msgid "Hide distant Areas"
+msgstr ""
+
#: ..\..\radiant\ui\about\AboutDialog.cpp:24
msgid "About DarkRadiant"
msgstr ""
@@ -1521,7 +1611,7 @@ msgid "Renderer: %s"
msgstr ""
#: ..\..\radiant\ui\animationpreview\MD5AnimationViewer.cpp:16
-#: xml_file_content.cpp:139
+#: xml_file_content.cpp:140
msgid "MD5 Animation Viewer"
msgstr ""
@@ -1556,7 +1646,7 @@ msgid "Shortcut List"
msgstr ""
#: ..\..\radiant\ui\commandlist\CommandList.cpp:53
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:94
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:116
#: xml_file_content.cpp:2
msgid "Command"
msgstr ""
@@ -1630,7 +1720,7 @@ msgstr ""
#: ..\..\radiant\ui\common\ShaderSelector.cpp:195
#: ..\..\radiant\ui\common\ShaderSelector.cpp:225
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:437
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:481
#: ..\..\plugins\eclasstree\EClassTree.cpp:143
#: ..\..\libs\wxutil\KeyValueTable.cpp:44
msgid "Value"
@@ -1678,7 +1768,7 @@ msgstr ""
#: ..\..\radiant\ui\common\SoundChooser.cpp:189
#: ..\..\radiant\ui\entitychooser\EntityClassChooser.cpp:290
#: ..\..\radiant\ui\modelselector\ModelSelector.cpp:340
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:380
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:396
msgid "Loading..."
msgstr ""
@@ -1711,12 +1801,12 @@ msgid "Custom properties defined for this entity class, if any"
msgstr ""
#: ..\..\radiant\ui\einspector\AddPropertyDialog.cpp:76
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:432
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:476
#: ..\..\plugins\eclasstree\EClassTree.cpp:140
msgid "Property"
msgstr ""
-#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:25
+#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:26
msgid "Choose entity class..."
msgstr ""
@@ -1728,41 +1818,42 @@ msgstr ""
msgid "Show help"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:292
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:312
msgid "Add property..."
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:296
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:317
msgid "Delete property"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:304
-msgid "Copy Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:325
+msgid "Copy Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:309
-msgid "Cut Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:330
+msgid "Cut Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:314
-msgid "Paste Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:335
+msgid "Paste Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:442
-msgid "?"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:347
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:350
+#: ..\..\plugins\uimanager\GroupDialog.cpp:28
+msgid "Entity"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:654
-#, c-format
-msgid "The name %s already exists in this map!"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:486
+msgid "?"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1064
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1200
#, c-format
msgid "Entity %d"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1076
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1212
#, c-format
msgid "Entity %d, Primitive %d"
msgstr ""
@@ -1771,7 +1862,7 @@ msgstr ""
msgid "Choose target entity..."
msgstr ""
-#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:78
+#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:71
#: ..\..\radiant\ui\einspector\Vector3PropertyEditor.cpp:62
msgid "Apply..."
msgstr ""
@@ -2033,59 +2124,53 @@ msgstr ""
msgid "Window Layout"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:93
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:84
msgid "Settings/Multi Monitor"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:112
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:103
msgid "Start DarkRadiant on monitor"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:131
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:122
msgid "Settings/Compatibility"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:133
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:124
msgid "Disable Windows Desktop Composition"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:267
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:256
msgid "Exit DarkRadiant"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:380
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:383
-#: ..\..\plugins\uimanager\GroupDialog.cpp:28
-msgid "Entity"
-msgstr ""
-
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:391
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:394
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:369
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:372
msgid "Media"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:402
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:405
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:381
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:384
msgid "Console"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:144
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:145
msgid "Camera Position"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:147
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:148
msgid "Top Left"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:149
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:150
msgid "Top Right"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:151
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:152
msgid "Bottom Left"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:153
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:154
msgid "Bottom Right"
msgstr ""
@@ -2381,7 +2466,7 @@ msgstr ""
msgid "Merge Entities"
msgstr ""
-#: ..\..\radiant\ui\ortho\OrthoContextMenu.cpp:74 xml_file_content.cpp:155
+#: ..\..\radiant\ui\ortho\OrthoContextMenu.cpp:74 xml_file_content.cpp:156
msgid "Make Visportal"
msgstr ""
@@ -2455,7 +2540,7 @@ msgid "Patch Inspector"
msgstr ""
#: ..\..\radiant\ui\patch\PatchInspector.cpp:29
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:55
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:56
#: ..\..\radiant\ui\transform\TransformDialog.cpp:38
msgid "Step:"
msgstr ""
@@ -2464,135 +2549,139 @@ msgstr ""
msgid "Patch Thicken"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:41
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:42
msgid "Choose Prefab"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:97
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:100
msgid "Rescan Prefab Folders"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:128
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:105
+msgid "Create Group out of Prefab parts"
+msgstr ""
+
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:140
msgid "Browse mod resources"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:131
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:143
msgid "Select recently used path:"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:133
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:145
msgid "Browse custom path:"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:532
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:553
msgid "<no description>"
msgstr ""
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:37
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:23
msgid "DarkRadiant Preferences"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:38
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
msgid "Surface Inspector"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
msgid "Texture Properties"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:41
msgid "Texture Operations"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:48
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
msgid "Horiz. Shift:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
msgid "Vert. Shift:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
msgid "Horiz. Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
msgid "Vert. Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
msgid "Rotation:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:54
#: xml_file_content.cpp:15
msgid "Shader:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:57
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
msgid "Fit Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:59
msgid "Fit"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:60
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
msgid "Align Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
msgid "Top"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
msgid "Bottom"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
#: xml_file_content.cpp:16
msgid "Right"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:65
#: xml_file_content.cpp:15
msgid "Left"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:66
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
msgid "Flip Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
msgid "Flip Horizontal"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:69
msgid "Flip Vertical"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:70
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
msgid "Modify Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
msgid "Natural"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:73
msgid "Normalise"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:74
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
msgid "Default Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:76
#: xml_file_content.cpp:9
msgid "Texture Lock"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:634
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:649
msgid "Both fit values must be > 0."
msgstr ""
@@ -2601,7 +2690,7 @@ msgid "Seek in Media Browser"
msgstr ""
#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:269
-#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:811
+#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:809
msgid "No shader"
msgstr ""
@@ -2701,7 +2790,7 @@ msgstr ""
msgid "Show Entity Names"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:205 xml_file_content.cpp:79
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:205 xml_file_content.cpp:80
msgid "Show Blocks"
msgstr ""
@@ -2709,15 +2798,15 @@ msgstr ""
msgid "Show Coordinates"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:207 xml_file_content.cpp:82
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:207 xml_file_content.cpp:83
msgid "Show Axes"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:208 xml_file_content.cpp:81
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:208 xml_file_content.cpp:82
msgid "Show Window Outline"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:209 xml_file_content.cpp:83
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:209 xml_file_content.cpp:84
msgid "Show Workzone"
msgstr ""
@@ -2729,6 +2818,10 @@ msgstr ""
msgid "Higher Selection Priority for Entities"
msgstr ""
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:665
+msgid "Shows the mouse position in the orthoview"
+msgstr ""
+
#: ..\..\radiant\xyview\tools\BrushCreatorTool.cpp:25
msgid "Drag-create Brush"
msgstr ""
@@ -2741,7 +2834,7 @@ msgstr ""
msgid "Drag Camera"
msgstr ""
-#: ..\..\radiant\xyview\tools\ClipperTool.cpp:21 xml_file_content.cpp:149
+#: ..\..\radiant\xyview\tools\ClipperTool.cpp:21 xml_file_content.cpp:150
#: xml_file_content.cpp:12 xml_file_content.cpp:17
msgid "Clipper"
msgstr ""
@@ -2766,7 +2859,7 @@ msgstr ""
msgid "YZ Side"
msgstr ""
-#: ..\..\radiant\xyview\XYWnd.cpp:637
+#: ..\..\radiant\xyview\XYWnd.cpp:498
#, c-format
msgid "x: %6.1lf y: %6.1lf z: %6.1lf"
msgstr ""
@@ -2785,7 +2878,7 @@ msgstr ""
msgid "Conversation Editor"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:278
+#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:280
#, c-format
msgid "Unable to create conversation Entity: class '%s' not found."
msgstr ""
@@ -2794,35 +2887,35 @@ msgstr ""
msgid "Edit Conversation"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:67
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:89
msgid "Actor (click to edit)"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:92
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:114
#: xml_file_content.cpp:1
msgid "Actor"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:96
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:118
msgid "Wait"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:201
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:223
#, c-format
msgid "Actor %d"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "yes"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "no"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:369
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:394
msgid "New Actor"
msgstr ""
@@ -3941,7 +4034,7 @@ msgstr ""
#: ..\..\plugins\dm.stimresponse\ResponseEditor.cpp:412
#: ..\..\plugins\dm.stimresponse\StimEditor.cpp:403
#: ..\..\plugins\uimanager\colourscheme\ColourSchemeEditor.cpp:95
-#: xml_file_content.cpp:179 xml_file_content.cpp:3 xml_file_content.cpp:7
+#: xml_file_content.cpp:180 xml_file_content.cpp:3 xml_file_content.cpp:7
#: xml_file_content.cpp:9 xml_file_content.cpp:15 xml_file_content.cpp:2
#: xml_file_content.cpp:5 xml_file_content.cpp:6 xml_file_content.cpp:18
msgid "Delete"
@@ -4069,7 +4162,8 @@ msgstr ""
msgid "Custom Stims"
msgstr ""
-#: ..\..\plugins\eclassmgr\EClassManager.cpp:330
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:327
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:328
msgid "Reloading Defs"
msgstr ""
@@ -4113,47 +4207,51 @@ msgstr ""
msgid "All Files"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:151
+#: ..\..\plugins\grid\Grid.cpp:55
+msgid "Current Grid Size"
+msgstr ""
+
+#: ..\..\plugins\grid\Grid.cpp:152
msgid "Settings/Grid"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:153
+#: ..\..\plugins\grid\Grid.cpp:154
msgid "Default Grid Size"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:157
+#: ..\..\plugins\grid\Grid.cpp:158
msgid "Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:158
+#: ..\..\plugins\grid\Grid.cpp:159
msgid "Dotted Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:159
+#: ..\..\plugins\grid\Grid.cpp:160
msgid "More Dotted Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:160
+#: ..\..\plugins\grid\Grid.cpp:161
msgid "Crosses"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:161
+#: ..\..\plugins\grid\Grid.cpp:162
msgid "Dots"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:162
+#: ..\..\plugins\grid\Grid.cpp:163
msgid "Big Dots"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:163
+#: ..\..\plugins\grid\Grid.cpp:164
msgid "Squares"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:165
+#: ..\..\plugins\grid\Grid.cpp:166
msgid "Major Grid Style"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:166
+#: ..\..\plugins\grid\Grid.cpp:167
msgid "Minor Grid Style"
msgstr ""
@@ -4182,24 +4280,25 @@ msgid "Incorrect map version: required %f, found %f"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:144
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:94
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:102
#, c-format
msgid "Primitive #%d: parse error"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:154
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:104
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:112
#, c-format
msgid "Primitive #%d: parse exception %s"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:245
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:195
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:203
#, c-format
msgid "Parsed invalid value '%s' for key '%s'"
msgstr ""
#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:125
+#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:234
#, c-format
msgid "BrushDefParser: invalid token '%s'"
msgstr ""
@@ -4269,23 +4368,23 @@ msgstr ""
msgid "Cannot save particle, it has not been registered yet."
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:316
-#: ..\..\plugins\particles\ParticlesManager.cpp:344
+#: ..\..\plugins\particles\ParticlesManager.cpp:325
+#: ..\..\plugins\particles\ParticlesManager.cpp:353
#, c-format
msgid "Cannot open file for writing: %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:357
+#: ..\..\plugins\particles\ParticlesManager.cpp:366
#, c-format
msgid "Cannot open file for reading: %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:404
+#: ..\..\plugins\particles\ParticlesManager.cpp:413
#, c-format
msgid "Could not remove the file %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:418
+#: ..\..\plugins\particles\ParticlesManager.cpp:427
#, c-format
msgid "Could not rename the temporary file %s"
msgstr ""
@@ -4299,7 +4398,7 @@ msgstr ""
msgid "Reload Scripts"
msgstr ""
-#: ..\..\plugins\script\ScriptMenu.cpp:51
+#: ..\..\plugins\script\ScriptMenu.cpp:60
msgid "No scripts available"
msgstr ""
@@ -4311,7 +4410,7 @@ msgstr ""
msgid "Run Script"
msgstr ""
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Loading Shaders"
msgstr ""
@@ -4350,20 +4449,16 @@ msgstr ""
msgid "_Filters"
msgstr ""
-#: ..\..\plugins\undo\UndoSystem.cpp:384
-msgid "Settings/Undo System"
+#: ..\..\plugins\uimanager\UIManager.cpp:115
+msgid "Describes available Mouse Commands"
msgstr ""
-#: ..\..\plugins\undo\UndoSystem.cpp:385
-msgid "Undo Queue Size"
-msgstr ""
-
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:31
-msgid "Save as Obj"
+#: ..\..\plugins\undo\UndoSystem.cpp:398
+msgid "Settings/Undo System"
msgstr ""
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:89
-msgid "Export Selection as OBJ..."
+#: ..\..\plugins\undo\UndoSystem.cpp:399
+msgid "Undo Queue Size"
msgstr ""
#: ..\..\libs\wxutil\dialog\MessageBox.cpp:20 xml_file_content.cpp:8
@@ -4502,7 +4597,7 @@ msgstr ""
msgid "Reload S&kins"
msgstr ""
-#: xml_file_content.cpp:16 xml_file_content.cpp:26
+#: xml_file_content.cpp:16 xml_file_content.cpp:28
msgid "Reload Materials"
msgstr ""
@@ -4662,496 +4757,496 @@ msgstr ""
msgid "&Texture Tool"
msgstr ""
-#: xml_file_content.cpp:61
-msgid "&Center"
+#: xml_file_content.cpp:60
+msgid "AAS Area Viewer"
msgstr ""
#: xml_file_content.cpp:62
-msgid "&Up Floor"
+msgid "&Center"
msgstr ""
#: xml_file_content.cpp:63
-msgid "&Down Floor"
+msgid "&Up Floor"
msgstr ""
#: xml_file_content.cpp:64
-msgid "Far Clip Plane In"
+msgid "&Down Floor"
msgstr ""
#: xml_file_content.cpp:65
-msgid "Far Clip Plane Out"
+msgid "Far Clip Plane In"
msgstr ""
#: xml_file_content.cpp:66
-msgid "Next leak spot"
+msgid "Far Clip Plane Out"
msgstr ""
#: xml_file_content.cpp:67
-msgid "Previous leak spot"
+msgid "Next leak spot"
msgstr ""
#: xml_file_content.cpp:68
-msgid "Orthographic"
+msgid "Previous leak spot"
msgstr ""
#: xml_file_content.cpp:69
-msgid "Next (XY, XZ, YZ)"
+msgid "Orthographic"
msgstr ""
#: xml_file_content.cpp:70
-msgid "XY (Top)"
+msgid "Next (XY, XZ, YZ)"
msgstr ""
#: xml_file_content.cpp:71
-msgid "YZ"
+msgid "XY (Top)"
msgstr ""
#: xml_file_content.cpp:72
-msgid "XZ"
+msgid "YZ"
msgstr ""
#: xml_file_content.cpp:73
-msgid "&XY 100%"
+msgid "XZ"
msgstr ""
#: xml_file_content.cpp:74
-msgid "&XY Zoom In"
+msgid "&XY 100%"
msgstr ""
#: xml_file_content.cpp:75
-msgid "&XY Zoom Out"
+msgid "&XY Zoom In"
msgstr ""
#: xml_file_content.cpp:76
-msgid "Show"
+msgid "&XY Zoom Out"
msgstr ""
#: xml_file_content.cpp:77
-msgid "Show &Angles"
+msgid "Show"
msgstr ""
#: xml_file_content.cpp:78
+msgid "Show &Angles"
+msgstr ""
+
+#: xml_file_content.cpp:79
msgid "Show &Names"
msgstr ""
-#: xml_file_content.cpp:80
+#: xml_file_content.cpp:81
msgid "Show C&oordinates"
msgstr ""
-#: xml_file_content.cpp:84
+#: xml_file_content.cpp:85
msgid "Show size info"
msgstr ""
-#: xml_file_content.cpp:85
+#: xml_file_content.cpp:86
msgid "Hide/Show"
msgstr ""
-#: xml_file_content.cpp:86
+#: xml_file_content.cpp:87
msgid "Hide Selected"
msgstr ""
-#: xml_file_content.cpp:87
+#: xml_file_content.cpp:88
msgid "Hide Deselected"
msgstr ""
-#: xml_file_content.cpp:88
+#: xml_file_content.cpp:89
msgid "Show hidden"
msgstr ""
-#: xml_file_content.cpp:90
+#: xml_file_content.cpp:91
msgid "&Switch off"
msgstr ""
-#: xml_file_content.cpp:91
+#: xml_file_content.cpp:92
msgid "Set from &XY view"
msgstr ""
-#: xml_file_content.cpp:92
+#: xml_file_content.cpp:93
msgid "Set from &Brush"
msgstr ""
-#: xml_file_content.cpp:93
+#: xml_file_content.cpp:94
msgid "Set from Se&lection"
msgstr ""
-#: xml_file_content.cpp:94
+#: xml_file_content.cpp:95
msgid "Colours..."
msgstr ""
-#: xml_file_content.cpp:95
+#: xml_file_content.cpp:96
msgid "Background Image..."
msgstr ""
-#: xml_file_content.cpp:96
+#: xml_file_content.cpp:97
msgid "Mo&dify"
msgstr ""
-#: xml_file_content.cpp:97 xml_file_content.cpp:16
+#: xml_file_content.cpp:98 xml_file_content.cpp:16
msgid "Components"
msgstr ""
-#: xml_file_content.cpp:98
+#: xml_file_content.cpp:99
msgid "&Edges"
msgstr ""
-#: xml_file_content.cpp:99
+#: xml_file_content.cpp:100
msgid "&Vertices"
msgstr ""
-#: xml_file_content.cpp:100
+#: xml_file_content.cpp:101
msgid "&Faces"
msgstr ""
-#: xml_file_content.cpp:101
+#: xml_file_content.cpp:102
msgid "En&tities"
msgstr ""
-#: xml_file_content.cpp:102
+#: xml_file_content.cpp:103
msgid "Nudge"
msgstr ""
-#: xml_file_content.cpp:103
+#: xml_file_content.cpp:104
msgid "Nudge Left"
msgstr ""
-#: xml_file_content.cpp:104
+#: xml_file_content.cpp:105
msgid "Nudge Right"
msgstr ""
-#: xml_file_content.cpp:105
+#: xml_file_content.cpp:106
msgid "Nudge Up"
msgstr ""
-#: xml_file_content.cpp:106
+#: xml_file_content.cpp:107
msgid "Nudge Down"
msgstr ""
-#: xml_file_content.cpp:107 xml_file_content.cpp:15
+#: xml_file_content.cpp:108 xml_file_content.cpp:15
msgid "Rotate"
msgstr ""
-#: xml_file_content.cpp:108
+#: xml_file_content.cpp:109
msgid "Rotate X"
msgstr ""
-#: xml_file_content.cpp:109
+#: xml_file_content.cpp:110
msgid "Rotate Y"
msgstr ""
-#: xml_file_content.cpp:110
+#: xml_file_content.cpp:111
msgid "Rotate Z"
msgstr ""
-#: xml_file_content.cpp:111
+#: xml_file_content.cpp:112
msgid "Mirror"
msgstr ""
-#: xml_file_content.cpp:112
+#: xml_file_content.cpp:113
msgid "Mirror &X"
msgstr ""
-#: xml_file_content.cpp:113
+#: xml_file_content.cpp:114
msgid "Mirror &Y"
msgstr ""
-#: xml_file_content.cpp:114
+#: xml_file_content.cpp:115
msgid "Mirror &Z"
msgstr ""
-#: xml_file_content.cpp:115 xml_file_content.cpp:10
+#: xml_file_content.cpp:116 xml_file_content.cpp:10
msgid "Rotate Objects independently"
msgstr ""
-#: xml_file_content.cpp:116
+#: xml_file_content.cpp:117
msgid "Rotate and scale..."
msgstr ""
-#: xml_file_content.cpp:117
+#: xml_file_content.cpp:118
msgid "&Grid"
msgstr ""
-#: xml_file_content.cpp:118
+#: xml_file_content.cpp:119
msgid "Snap selected to grid"
msgstr ""
-#: xml_file_content.cpp:119
+#: xml_file_content.cpp:120
msgid "Grid0.125"
msgstr ""
-#: xml_file_content.cpp:120
+#: xml_file_content.cpp:121
msgid "Grid0.25"
msgstr ""
-#: xml_file_content.cpp:121
+#: xml_file_content.cpp:122
msgid "Grid0.5"
msgstr ""
-#: xml_file_content.cpp:122
+#: xml_file_content.cpp:123
msgid "Grid1"
msgstr ""
-#: xml_file_content.cpp:123
+#: xml_file_content.cpp:124
msgid "Grid2"
msgstr ""
-#: xml_file_content.cpp:124
+#: xml_file_content.cpp:125
msgid "Grid4"
msgstr ""
-#: xml_file_content.cpp:125
+#: xml_file_content.cpp:126
msgid "Grid8"
msgstr ""
-#: xml_file_content.cpp:126
+#: xml_file_content.cpp:127
msgid "Grid16"
msgstr ""
-#: xml_file_content.cpp:127
+#: xml_file_content.cpp:128
msgid "Grid32"
msgstr ""
-#: xml_file_content.cpp:128
+#: xml_file_content.cpp:129
msgid "Grid64"
msgstr ""
-#: xml_file_content.cpp:129
+#: xml_file_content.cpp:130
msgid "Grid128"
msgstr ""
-#: xml_file_content.cpp:130
+#: xml_file_content.cpp:131
msgid "Grid256"
msgstr ""
-#: xml_file_content.cpp:131
+#: xml_file_content.cpp:132
msgid "M&ap"
msgstr ""
-#: xml_file_content.cpp:132
+#: xml_file_content.cpp:133
msgid "Find brush..."
msgstr ""
-#: xml_file_content.cpp:133
+#: xml_file_content.cpp:134
msgid "Find and replace textures..."
msgstr ""
-#: xml_file_content.cpp:134
+#: xml_file_content.cpp:135
msgid "Map info..."
msgstr ""
-#: xml_file_content.cpp:135
+#: xml_file_content.cpp:136
msgid "E&ntity"
msgstr ""
-#: xml_file_content.cpp:136
+#: xml_file_content.cpp:137
msgid "&Revert group to worldspawn"
msgstr ""
-#: xml_file_content.cpp:137
+#: xml_file_content.cpp:138
msgid "&Connect selected entities"
msgstr ""
-#: xml_file_content.cpp:138
+#: xml_file_content.cpp:139
msgid "&Bind selected entities"
msgstr ""
-#: xml_file_content.cpp:140
+#: xml_file_content.cpp:141
msgid "B&rush"
msgstr ""
-#: xml_file_content.cpp:141
+#: xml_file_content.cpp:142
msgid "Prism..."
msgstr ""
-#: xml_file_content.cpp:142
+#: xml_file_content.cpp:143
msgid "Cone..."
msgstr ""
-#: xml_file_content.cpp:143
+#: xml_file_content.cpp:144
msgid "Sphere..."
msgstr ""
-#: xml_file_content.cpp:144
+#: xml_file_content.cpp:145
msgid "CSG"
msgstr ""
-#: xml_file_content.cpp:145
+#: xml_file_content.cpp:146
msgid "Make &Hollow"
msgstr ""
-#: xml_file_content.cpp:146
+#: xml_file_content.cpp:147
msgid "Make &Room"
msgstr ""
-#: xml_file_content.cpp:147
+#: xml_file_content.cpp:148
msgid "CSG &Subtract"
msgstr ""
-#: xml_file_content.cpp:148
+#: xml_file_content.cpp:149
msgid "CSG &Merge"
msgstr ""
-#: xml_file_content.cpp:150
+#: xml_file_content.cpp:151
msgid "Clip Selection"
msgstr ""
-#: xml_file_content.cpp:151
+#: xml_file_content.cpp:152
msgid "Split Selection"
msgstr ""
-#: xml_file_content.cpp:152
+#: xml_file_content.cpp:153
msgid "Flip Clip Orientation"
msgstr ""
-#: xml_file_content.cpp:153
+#: xml_file_content.cpp:154
msgid "Texture lock"
msgstr ""
-#: xml_file_content.cpp:154
+#: xml_file_content.cpp:155
msgid "Create Decal Patches"
msgstr ""
-#: xml_file_content.cpp:156
+#: xml_file_content.cpp:157
msgid "Make Detail"
msgstr ""
-#: xml_file_content.cpp:157
+#: xml_file_content.cpp:158
msgid "Make Structural"
msgstr ""
-#: xml_file_content.cpp:158
+#: xml_file_content.cpp:159
msgid "&Patch"
msgstr ""
-#: xml_file_content.cpp:159
+#: xml_file_content.cpp:160
msgid "Create Simple Patch Mesh"
msgstr ""
-#: xml_file_content.cpp:160
+#: xml_file_content.cpp:161
msgid "Create End cap"
msgstr ""
-#: xml_file_content.cpp:161
+#: xml_file_content.cpp:162
msgid "Create Bevel"
msgstr ""
-#: xml_file_content.cpp:162
+#: xml_file_content.cpp:163
msgid "Create Cone"
msgstr ""
-#: xml_file_content.cpp:163
+#: xml_file_content.cpp:164
msgid "Create Cylinder"
msgstr ""
-#: xml_file_content.cpp:164
+#: xml_file_content.cpp:165
msgid "Create Sphere"
msgstr ""
-#: xml_file_content.cpp:165
+#: xml_file_content.cpp:166
msgid "More cylinders"
msgstr ""
-#: xml_file_content.cpp:166
+#: xml_file_content.cpp:167
msgid "Create Dense Cylinder"
msgstr ""
-#: xml_file_content.cpp:167
+#: xml_file_content.cpp:168
msgid "Create Very Dense Cylinder"
msgstr ""
-#: xml_file_content.cpp:168
+#: xml_file_content.cpp:169
msgid "Create Square Cylinder"
msgstr ""
-#: xml_file_content.cpp:169
+#: xml_file_content.cpp:170
msgid "Insert"
msgstr ""
-#: xml_file_content.cpp:170
+#: xml_file_content.cpp:171
msgid "Insert 2 Columns at the beginning"
msgstr ""
-#: xml_file_content.cpp:171
+#: xml_file_content.cpp:172
msgid "Insert 2 Columns at the end"
msgstr ""
-#: xml_file_content.cpp:172
+#: xml_file_content.cpp:173
msgid "Insert 2 Rows at the beginning"
msgstr ""
-#: xml_file_content.cpp:173
+#: xml_file_content.cpp:174
msgid "Insert 2 Rows at the end"
msgstr ""
-#: xml_file_content.cpp:174
+#: xml_file_content.cpp:175
msgid "Append"
msgstr ""
-#: xml_file_content.cpp:175
+#: xml_file_content.cpp:176
msgid "Append 2 columns at the beginning"
msgstr ""
-#: xml_file_content.cpp:176
+#: xml_file_content.cpp:177
msgid "Append 2 columns at the end"
msgstr ""
-#: xml_file_content.cpp:177
+#: xml_file_content.cpp:178
msgid "Append 2 rows at the beginning"
msgstr ""
-#: xml_file_content.cpp:178
+#: xml_file_content.cpp:179
msgid "Append 2 rows at the end"
msgstr ""
-#: xml_file_content.cpp:180
-msgid "Delete 2 columns from the beginning"
-msgstr ""
-
#: xml_file_content.cpp:181
-msgid "Delete 2 columns from the end"
+msgid "Delete 2 columns from the beginning"
msgstr ""
#: xml_file_content.cpp:182
-msgid "Delete 2 rows from the beginning"
+msgid "Delete 2 columns from the end"
msgstr ""
#: xml_file_content.cpp:183
-msgid "Delete 2 rows from the end"
+msgid "Delete 2 rows from the beginning"
msgstr ""
#: xml_file_content.cpp:184
-msgid "Matrix"
+msgid "Delete 2 rows from the end"
msgstr ""
#: xml_file_content.cpp:185
-msgid "Invert"
+msgid "Matrix"
msgstr ""
#: xml_file_content.cpp:186
-msgid "Re-disperse"
+msgid "Invert"
msgstr ""
#: xml_file_content.cpp:187
-msgid "Rows"
+msgid "Re-disperse"
msgstr ""
#: xml_file_content.cpp:188
-msgid "Columns"
+msgid "Rows"
msgstr ""
#: xml_file_content.cpp:189
-msgid "Transpose"
+msgid "Columns"
msgstr ""
#: xml_file_content.cpp:190
-msgid "Thicken Selected Patches"
+msgid "Transpose"
msgstr ""
#: xml_file_content.cpp:191
-msgid "Cap Selection"
+msgid "Thicken Selected Patches"
msgstr ""
#: xml_file_content.cpp:192
-msgid "Cycle Cap Texture"
+msgid "Cap Selection"
msgstr ""
#: xml_file_content.cpp:193
@@ -5391,58 +5486,66 @@ msgid "Make Room"
msgstr ""
#: xml_file_content.cpp:20
-msgid "Put caps on the current patch"
+msgid "Group selected items"
msgstr ""
#: xml_file_content.cpp:21
-msgid "Creates a NURBS curve"
+msgid "Ungroup selected items"
msgstr ""
#: xml_file_content.cpp:22
-msgid "Convert the selected curve (NURBS <-> CatmullRom)"
+msgid "Put caps on the current patch"
msgstr ""
#: xml_file_content.cpp:23
-msgid "Appends a control point to the selected curves"
+msgid "Creates a NURBS curve"
msgstr ""
#: xml_file_content.cpp:24
-msgid "Inserts a curve control point before the selected ones"
+msgid "Convert the selected curve (NURBS <-> CatmullRom)"
msgstr ""
#: xml_file_content.cpp:25
-msgid "Removes the selected curve control points"
+msgid "Appends a control point to the selected curves"
+msgstr ""
+
+#: xml_file_content.cpp:26
+msgid "Inserts a curve control point before the selected ones"
msgstr ""
#: xml_file_content.cpp:27
+msgid "Removes the selected curve control points"
+msgstr ""
+
+#: xml_file_content.cpp:29
msgid "Find & Replace"
msgstr ""
-#: xml_file_content.cpp:28
+#: xml_file_content.cpp:30
msgid "Decrease Grid Size"
msgstr ""
-#: xml_file_content.cpp:29
+#: xml_file_content.cpp:31
msgid "Increase Grid Size"
msgstr ""
-#: xml_file_content.cpp:30
+#: xml_file_content.cpp:32
msgid "Snap to Grid"
msgstr ""
-#: xml_file_content.cpp:31
+#: xml_file_content.cpp:33
msgid "Merge Selection"
msgstr ""
-#: xml_file_content.cpp:32
+#: xml_file_content.cpp:34
msgid "Flip Selection Horiz (S-Axis)"
msgstr ""
-#: xml_file_content.cpp:33
+#: xml_file_content.cpp:35
msgid "Flip Selection Vertical (T-Axis)"
msgstr ""
-#: xml_file_content.cpp:34
+#: xml_file_content.cpp:36
msgid "Select Related Items"
msgstr ""
diff --git a/install/i18n/de/LC_MESSAGES/darkradiant.mo b/install/i18n/de/LC_MESSAGES/darkradiant.mo
index cc2aa2f..01725d6 100644
Binary files a/install/i18n/de/LC_MESSAGES/darkradiant.mo and b/install/i18n/de/LC_MESSAGES/darkradiant.mo differ
diff --git a/install/i18n/de/LC_MESSAGES/darkradiant.po b/install/i18n/de/LC_MESSAGES/darkradiant.po
index 4669bd6..a219b76 100644
--- a/install/i18n/de/LC_MESSAGES/darkradiant.po
+++ b/install/i18n/de/LC_MESSAGES/darkradiant.po
@@ -2,9 +2,9 @@ msgid ""
msgstr ""
"Project-Id-Version: DarkRadiant\n"
"Report-Msgid-Bugs-To: greebo at angua.at\n"
-"POT-Creation-Date: 2016-01-05 11:54+0100\n"
-"PO-Revision-Date: 2016-01-05 11:59+0100\n"
-"Last-Translator: greebo <greebo at angua.at>\n"
+"POT-Creation-Date: 2016-11-18 18:32+0100\n"
+"PO-Revision-Date: 2016-11-18 18:36+0100\n"
+"Last-Translator: greebo <greebo at thedarkmod.com>\n"
"Language-Team: The Dark Mod\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -84,12 +84,12 @@ msgstr "Invertiere vertikale Mausachse (freier Umsichtsmodus)"
msgid "Solid selection boxes"
msgstr "Feste Auswahlrahmen"
-#: ..\..\radiant\camera\CameraSettings.cpp:75
+#: ..\..\radiant\camera\CameraSettings.cpp:74
msgid "Show camera toolbar"
msgstr "Zeige Toolbar im Kamera-Fenster"
#: ..\..\radiant\camera\FloatingCamWnd.cpp:18
-#: xml_file_content.cpp:60
+#: xml_file_content.cpp:61
msgid "Camera"
msgstr "Kamera"
@@ -101,27 +101,31 @@ msgstr "Umsichtsmodus"
msgid "Jump to Object"
msgstr "Zu Objekt springen"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:97
+#: ..\..\radiant\camera\tools\PanViewTool.h:23
+msgid "Pan Camera View"
+msgstr "Kamera-Ansicht verschieben"
+
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:116
msgid "Pick Shader"
msgstr "Shader auswählen"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:120
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:139
msgid "Paste Shader Projected"
msgstr "Shader einfügen (Projektion)"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:138
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:158
msgid "Paste Shader Natural"
msgstr "Shader einfügen (Natürliche Skalierung)"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:156
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:177
msgid "Paste Texture Coordinates"
msgstr "Texturkoordinaten einfügen"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:174
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:196
msgid "Paste Shader to all Brush Faces"
msgstr "Shader einfügen (gesamter Brush)"
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:192
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:215
msgid "Paste Shader Name"
msgstr "Shadernamen einfügen"
@@ -137,40 +141,40 @@ msgstr "Clipper verwendet Caulk-Textur für neu erzeugte Faces."
msgid "Caulk shader name"
msgstr "Name des Caulk Shaders"
-#: ..\..\radiant\layers\LayerSystem.cpp:34
+#: ..\..\radiant\layers\LayerSystem.cpp:36
msgid "Default"
msgstr "Standard"
-#: ..\..\radiant\layers\LayerSystem.cpp:37
+#: ..\..\radiant\layers\LayerSystem.cpp:39
msgid "Create Layer..."
msgstr "Neuer Layer..."
-#: ..\..\radiant\layers\LayerSystem.cpp:39
+#: ..\..\radiant\layers\LayerSystem.cpp:41
msgid "Add to Layer..."
msgstr "Zu Layer hinzufügen..."
-#: ..\..\radiant\layers\LayerSystem.cpp:40
+#: ..\..\radiant\layers\LayerSystem.cpp:42
msgid "Move to Layer..."
msgstr "Nach Layer verschieben..."
-#: ..\..\radiant\layers\LayerSystem.cpp:41
+#: ..\..\radiant\layers\LayerSystem.cpp:43
msgid "Remove from Layer..."
msgstr "Von Layer entfernen..."
-#: ..\..\radiant\layers\LayerSystem.cpp:536
+#: ..\..\radiant\layers\LayerSystem.cpp:550
#: ..\..\plugins\particles\editor\ParticleEditor.cpp:1537
msgid "Enter Name"
msgstr "Namen eingeben"
-#: ..\..\radiant\layers\LayerSystem.cpp:537
+#: ..\..\radiant\layers\LayerSystem.cpp:551
msgid "Enter Layer Name"
msgstr "Ebenennamen eingeben"
-#: ..\..\radiant\layers\LayerSystem.cpp:549
+#: ..\..\radiant\layers\LayerSystem.cpp:563
msgid "Cannot create layer with empty name."
msgstr "Es ist nicht möglich eine Ebene ohne Namen zu erstellen."
-#: ..\..\radiant\layers\LayerSystem.cpp:563
+#: ..\..\radiant\layers\LayerSystem.cpp:577
msgid "This name already exists."
msgstr "Dieser Name existiert bereits"
@@ -201,36 +205,44 @@ msgstr "Lade Map"
msgid "Loading entity %d\n"
msgstr "Lade Entity %d\n"
-#: ..\..\radiant\map\AutoSaver.cpp:299
+#: ..\..\radiant\map\AutoSaver.cpp:276
msgid "Settings/Autosave"
msgstr "Einstellungen/Automatisches Speichern"
-#: ..\..\radiant\map\AutoSaver.cpp:302
+#: ..\..\radiant\map\AutoSaver.cpp:279
msgid "Enable Autosave"
msgstr "Aktiviere automatisches Speichern"
-#: ..\..\radiant\map\AutoSaver.cpp:303
+#: ..\..\radiant\map\AutoSaver.cpp:280
msgid "Autosave Interval (in minutes)"
msgstr "Speicherintervall"
# Snapshots oder Schnappschüsse?
-#: ..\..\radiant\map\AutoSaver.cpp:305
+#: ..\..\radiant\map\AutoSaver.cpp:282
msgid "Save Snapshots"
msgstr "Speichere Schnappschüsse"
# Snapshot oder Schnappschuss?
-#: ..\..\radiant\map\AutoSaver.cpp:306
+#: ..\..\radiant\map\AutoSaver.cpp:283
msgid "Snapshot folder (relative to map folder)"
msgstr "Schnappschussverzeichniss (relativ zu map Verzeichniss)"
-#: ..\..\radiant\map\AutoSaver.cpp:307
+#: ..\..\radiant\map\AutoSaver.cpp:284
msgid "Max Snapshot Folder size (MB)"
msgstr "Maximale Grösse des Schnappschussverzeichnisses (MB)"
-#: ..\..\radiant\map\CounterManager.cpp:67
+#: ..\..\radiant\map\CounterManager.cpp:63
+msgid ""
+"Number of brushes/patches/entities in this map\n"
+"(Number of selected items shown in parentheses)"
+msgstr ""
+"Anzahl der Brushes/Patches/Entities in der Map\n"
+"(Anzahl der selektierten Elemente in Klammern)"
+
+#: ..\..\radiant\map\CounterManager.cpp:81
#, c-format
-msgid "Brushes: %lu Patches: %lu Entities: %lu"
-msgstr "Brushes: %lu Patches: %lu Entities: %lu"
+msgid "Brushes: %lu (%lu) Patches: %lu (%lu) Entities: %lu (%lu)"
+msgstr "Brushes: %lu (%lu) Patches: %lu (%lu) Entities: %lu (%lu)"
#: ..\..\radiant\map\FindMapElements.cpp:95
msgid "Find Brush"
@@ -244,38 +256,38 @@ msgstr "Entitynummer:"
msgid "Brush Number:"
msgstr "Brushnummer:"
-#: ..\..\radiant\map\InfoFile.cpp:73
+#: ..\..\radiant\map\infofile\InfoFile.cpp:70
msgid "Map Info File Version invalid"
msgstr "Ungültige Map Info File Verson"
-#: ..\..\radiant\map\Map.cpp:59
+#: ..\..\radiant\map\Map.cpp:62
msgid "unnamed.map"
msgstr "unbenannt.map"
-#: ..\..\radiant\map\Map.cpp:182
-#: ..\..\radiant\map\Map.cpp:518
-#: ..\..\radiant\map\Map.cpp:610
-#: ..\..\radiant\map\Map.cpp:638
-#: ..\..\radiant\RadiantModule.cpp:134
+#: ..\..\radiant\map\Map.cpp:106
+#: ..\..\radiant\map\Map.cpp:431
+#: ..\..\radiant\map\Map.cpp:522
+#: ..\..\radiant\map\Map.cpp:550
+#: ..\..\radiant\RadiantModule.cpp:135
#: ..\..\radiant\referencecache\ModelCache.cpp:245
#: ..\..\radiant\referencecache\ModelCache.cpp:261
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Processing..."
msgstr "Vorgang läuft..."
-#: ..\..\radiant\map\Map.cpp:182
+#: ..\..\radiant\map\Map.cpp:106
msgid "Loading textures..."
msgstr "Lade Texturen..."
-#: ..\..\radiant\map\Map.cpp:518
+#: ..\..\radiant\map\Map.cpp:431
msgid "Saving Map"
msgstr "Speichere Map"
-#: ..\..\radiant\map\Map.cpp:569
+#: ..\..\radiant\map\Map.cpp:481
msgid "Importing..."
msgstr "Importiere..."
-#: ..\..\radiant\map\Map.cpp:664
+#: ..\..\radiant\map\Map.cpp:576
#, c-format
msgid ""
"Save changes to map \"%s\"\n"
@@ -284,17 +296,17 @@ msgstr ""
"Sollen die Änderungen an der Map \"%s\"\n"
"vor dem Schließen gespeichert werden?"
-#: ..\..\radiant\map\Map.cpp:672
+#: ..\..\radiant\map\Map.cpp:584
#, c-format
msgid "%d minutes"
msgstr "%d Minuten"
-#: ..\..\radiant\map\Map.cpp:676
+#: ..\..\radiant\map\Map.cpp:588
#, c-format
msgid "%d seconds"
msgstr "%d Sekunden"
-#: ..\..\radiant\map\Map.cpp:680
+#: ..\..\radiant\map\Map.cpp:592
#, c-format
msgid ""
"If you don't save, changes from the last %s\n"
@@ -303,40 +315,40 @@ msgstr ""
"Wenn Du nicht sicherst, gehen die Änderungen\n"
"der letzten %s verloren."
-#: ..\..\radiant\map\Map.cpp:738
+#: ..\..\radiant\map\Map.cpp:650
msgid "Save Map"
msgstr "Map speichern"
-#: ..\..\radiant\map\Map.cpp:778
+#: ..\..\radiant\map\Map.cpp:690
msgid "Save Copy As..."
msgstr "Speichere Kopie als..."
-#: ..\..\radiant\map\Map.cpp:854
+#: ..\..\radiant\map\Map.cpp:781
msgid "New Map"
msgstr "Neue Map"
-#: ..\..\radiant\map\Map.cpp:865
+#: ..\..\radiant\map\Map.cpp:790
#: ..\..\radiant\ui\mru\MRU.cpp:93
msgid "Open Map"
msgstr "Map öffnen"
-#: ..\..\radiant\map\Map.cpp:869
+#: ..\..\radiant\map\Map.cpp:794
msgid "Open map"
msgstr "Map öffnen"
-#: ..\..\radiant\map\Map.cpp:883
+#: ..\..\radiant\map\Map.cpp:808
msgid "Import map"
msgstr "Map importieren"
-#: ..\..\radiant\map\Map.cpp:912
+#: ..\..\radiant\map\Map.cpp:837
msgid "Export selection"
msgstr "Auswahl exportieren"
-#: ..\..\radiant\map\Map.cpp:927
+#: ..\..\radiant\map\Map.cpp:852
msgid "Save selected as Prefab"
msgstr "Auswahl als Prefab speichern"
-#: ..\..\radiant\map\Map.cpp:1008
+#: ..\..\radiant\map\Map.cpp:933
#, c-format
msgid ""
"Failure reading map from clipboard:\n"
@@ -350,42 +362,33 @@ msgid "Map"
msgstr "Map"
#: ..\..\radiant\map\MapFileManager.cpp:36
-#: xml_file_content.cpp:89
+#: xml_file_content.cpp:90
msgid "Region"
msgstr "Region"
#: ..\..\radiant\map\MapFileManager.cpp:37
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:327
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:343
msgid "Prefab"
msgstr "Prefab"
-#: ..\..\radiant\map\MapResource.cpp:273
-#: ..\..\radiant\map\MapResource.cpp:641
+#: ..\..\radiant\map\MapResource.cpp:257
+#: ..\..\radiant\map\MapResource.cpp:529
#, c-format
msgid "File is write-protected: %s"
msgstr "Datei ist schreibgeschützt: %s"
-#: ..\..\radiant\map\MapResource.cpp:434
-#, c-format
-msgid ""
-"Failure opening map file:\n"
-"%s"
-msgstr ""
-"Fehler beim Öffnen der Mapdatei:\n"
-"%s"
-
-#: ..\..\radiant\map\MapResource.cpp:476
+#: ..\..\radiant\map\MapResource.cpp:363
#, c-format
msgid ""
"Could not determine map format of file:\n"
"%s"
msgstr "Konnte das Format der Mapdatei nicht bestimmen: %s"
-#: ..\..\radiant\map\MapResource.cpp:602
+#: ..\..\radiant\map\MapResource.cpp:410
msgid "Map loading cancelled"
msgstr "Ladevorgang abgebrochen"
-#: ..\..\radiant\map\MapResource.cpp:614
+#: ..\..\radiant\map\MapResource.cpp:422
#, c-format
msgid ""
"Failure reading map file:\n"
@@ -398,40 +401,50 @@ msgstr ""
"\n"
"%s"
-#: ..\..\radiant\map\MapResource.cpp:706
+#: ..\..\radiant\map\MapResource.cpp:485
+#: ..\..\radiant\map\MapResource.cpp:504
+#, c-format
+msgid ""
+"Failure opening file:\n"
+"%s"
+msgstr ""
+"Fehler beim Öffnen der Datei:\n"
+"%s"
+
+#: ..\..\radiant\map\MapResource.cpp:594
msgid "Map writing cancelled"
msgstr "Schreibvorgang abgebrochen"
-#: ..\..\radiant\map\MapResource.cpp:721
+#: ..\..\radiant\map\MapResource.cpp:609
msgid "Could not open output streams for writing"
msgstr "Fehler beim Öffnen der Output-Streams"
-#: ..\..\radiant\map\PointFile.cpp:116
+#: ..\..\radiant\map\PointFile.cpp:126
#, c-format
msgid "Could not open pointfile: %s"
msgstr "Konnte das Pointfile nicht öffnen: %s"
-#: ..\..\radiant\map\RegionManager.cpp:203
+#: ..\..\radiant\map\RegionManager.cpp:173
msgid "Warning: Camera not within region, can't set info_player_start."
msgstr "Warnung: die Kamera befindet sich nicht innerhalb der Region, konnte daher den Spielerstartpunkt nicht setzen."
-#: ..\..\radiant\map\RegionManager.cpp:293
+#: ..\..\radiant\map\RegionManager.cpp:261
msgid "Could not set Region: XY Top View not found."
msgstr "Konnte Region nicht festlegen, weil die XY-Ansicht nicht gefunden wurde."
-#: ..\..\radiant\map\RegionManager.cpp:320
+#: ..\..\radiant\map\RegionManager.cpp:288
msgid "Could not set Region: please select a single Brush."
msgstr "Kann Region nicht festlegen: bitte einen einzelnen Brush auswählen."
-#: ..\..\radiant\map\RegionManager.cpp:345
+#: ..\..\radiant\map\RegionManager.cpp:313
msgid "This command is not available in component mode."
msgstr "Dieser Befehl steht im Komponentenmodus nicht zur Verfügung."
-#: ..\..\radiant\map\RegionManager.cpp:351
+#: ..\..\radiant\map\RegionManager.cpp:319
msgid "Could not set Region: nothing selected."
msgstr "Kann keine Region festlegen: keine Elemente ausgewählt."
-#: ..\..\radiant\map\RegionManager.cpp:368
+#: ..\..\radiant\map\RegionManager.cpp:336
msgid "Export region"
msgstr "Exportiere Region"
@@ -448,7 +461,7 @@ msgstr "Initialisiere Modul: %s"
msgid "Initialising Modules"
msgstr "Initialisiere Module"
-#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:165
+#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:162
msgid "Modules initialised"
msgstr "Module initialisiert"
@@ -482,7 +495,7 @@ msgstr "Kann keine Bevel-Caps erzeugen, Patch muss eine Breite von 3 haben"
msgid "Cannot create cylinder-cap, patch must have a width of 9."
msgstr "Kann keine Zylinder-Caps erzeugen, Patch muss eine Breite von 9 haben"
-#: ..\..\radiant\patch\Patch.cpp:1667
+#: ..\..\radiant\patch\Patch.cpp:1639
msgid "Sorry. Patch is not suitable for this kind of operation."
msgstr "Patch ist nicht geeignet für diese Operation."
@@ -498,11 +511,11 @@ msgstr "Patch-Tesselierungsgrenzwert"
#: ..\..\radiant\settings\GameManager.cpp:97
#: ..\..\radiant\settings\GameManager.cpp:323
#: ..\..\radiant\settings\GameManager.cpp:344
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:198
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:169
msgid "Game"
msgstr "Spiel"
-#: ..\..\radiant\RadiantModule.cpp:238
+#: ..\..\radiant\RadiantModule.cpp:239
msgid "Settings"
msgstr "Einstellungen"
@@ -535,29 +548,42 @@ msgstr "Kann Kontrollpunkte nicht einfügen, keine Kurven ausgewählt."
msgid "Can't convert curves - no entities with curves selected."
msgstr "Kann Kurve nicht konvertieren, keine Kurven ausgewählt."
-#: ..\..\radiant\selection\algorithm\Entity.cpp:62
+#: ..\..\radiant\selection\algorithm\Entity.cpp:82
+#, c-format
+msgid "The name %s already exists in this map!"
+msgstr "Der Name %s existiert bereits in dieser Map!"
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:106
+msgid "Cannot set classname to an empty string."
+msgstr "Der Klassenname darf nicht leer sein"
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:112
+msgid "Cannot change classname to worldspawn."
+msgstr "Der Klassenname darf nicht auf worldspawn gesetzt werden."
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:131
msgid "Cannot change classname of worldspawn entity."
msgstr "Der Klassenname der Worldspawn-Entity darf nicht geändert werden."
-#: ..\..\radiant\selection\algorithm\Entity.cpp:104
+#: ..\..\radiant\selection\algorithm\Entity.cpp:169
msgid "Critical: Cannot find selected entities."
msgstr "Kritischer Fehler: kann ausgewählte Entities nicht finden."
-#: ..\..\radiant\selection\algorithm\Entity.cpp:109
-#: ..\..\radiant\selection\algorithm\Entity.cpp:125
+#: ..\..\radiant\selection\algorithm\Entity.cpp:174
+#: ..\..\radiant\selection\algorithm\Entity.cpp:190
msgid "Exactly two entities must be selected for this operation."
msgstr "Für diese Operation müssen genau zwei Entities ausgewählt sein."
-#: ..\..\radiant\selection\algorithm\Entity.cpp:171
+#: ..\..\radiant\selection\algorithm\Entity.cpp:236
#, c-format
msgid "Unable to create entity %s, no brushes selected."
msgstr "Entity %s kann nicht erzeugt werden. Keine Brushes ausgewählt."
-#: ..\..\radiant\selection\algorithm\Group.cpp:236
+#: ..\..\radiant\selection\algorithm\Group.cpp:234
msgid "Cannot reparent primitives to entity. Please select at least one brush/patch and exactly one entity.(The entity has to be selected last.)"
msgstr "Kann die ausgewählten Primitive nicht neu zuordnen. Bitte zumindest einen Brush/Patch sowie eine Entity auswählen. (Die Entity muss als letztes ausgewählt worden sein.)"
-#: ..\..\radiant\selection\algorithm\Group.cpp:386
+#: ..\..\radiant\selection\algorithm\Group.cpp:384
msgid ""
"Cannot merge entities, the selection must consist of func_* entities only.\n"
"(The first selected entity will be preserved.)"
@@ -565,11 +591,39 @@ msgstr ""
"Kann Entities nicht zusammenführen, die Auswahl muss ausschließlich aus func_*-Entities bestehen.\n"
"(Die zuerst ausgewählte Entity bleibt dabei erhalten.)"
+#: ..\..\radiant\selection\algorithm\Group.cpp:394
+msgid "Groups can be formed in Primitive selection mode only"
+msgstr "Gruppen können nur im Primitiv-Selektionsmodus erstellt werden"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:399
+msgid "Nothing selected, cannot group anything"
+msgstr "Nichts ausgewählt, kann keine Gruppe erstellen"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:404
+msgid "Select more than one element to form a group"
+msgstr "Um eine Gruppe zu erstellen muss mehr als ein Element ausgewählt werden"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:430
+msgid "The selected elements already form a group"
+msgstr "Die selektierten Elemente bilden bereits eine Gruppe"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:455
+msgid "Groups can be dissolved in Primitive selection mode only"
+msgstr "Gruppen können nur im Primitiv-Selektionsmodus aufgelöst werden"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:460
+msgid "Nothing selected, cannot un-group anything"
+msgstr "Nichts ausgewählt, kann keine Gruppierung auflösen"
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:480
+msgid "The selected elements aren't part of any group"
+msgstr "Keines der selektierten Elemente ist Teil einer Gruppe"
+
#: ..\..\radiant\selection\algorithm\Patch.cpp:60
msgid "Cannot create caps, no patches selected."
msgstr "Kann keine Caps erzeugen, da keine Patches ausgewählt sind."
-#: ..\..\radiant\selection\algorithm\Patch.cpp:208
+#: ..\..\radiant\selection\algorithm\Patch.cpp:197
msgid "Cannot thicken patch. Nothing selected."
msgstr "Nichts ausgewählt: kann Patch nicht extrudieren."
@@ -600,42 +654,52 @@ msgstr "Keine Brushes ausgewählt."
msgid "At least one brush must be selected for this operation."
msgstr "Für diese Operation muss mindestens ein Brush ausgewählt sein."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:285
+#: ..\..\radiant\selection\algorithm\Shader.cpp:307
msgid ""
"Can't paste shader to entire brush.\n"
"Target is not a brush."
msgstr "Kann Shader nicht auf gesamten Brush anwenden, das Ziel ist kein Brush."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:320
+#: ..\..\radiant\selection\algorithm\Shader.cpp:346
msgid ""
"Can't paste Texture Coordinates.\n"
"Target patch dimensions must match."
msgstr "Kann Texturkoordinaten nicht kopieren, da die Patch-Dimensionen nicht passend sind."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:327
+#: ..\..\radiant\selection\algorithm\Shader.cpp:355
msgid "Can't paste Texture Coordinates from patches to faces."
msgstr "Es ist nicht möglich, Texturkoordinaten von Patches auf Faces zu kopieren."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:332
+#: ..\..\radiant\selection\algorithm\Shader.cpp:361
msgid "Can't paste Texture Coordinates from faces."
msgstr "Es ist nicht möglich, Texturkoordinaten von Faces zu kopieren."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:388
+#: ..\..\radiant\selection\algorithm\Shader.cpp:417
msgid "Can't copy Shader. Couldn't retrieve patch."
msgstr "Konnte Patch nicht casten, Shader wurde nicht kopiert."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:398
+#: ..\..\radiant\selection\algorithm\Shader.cpp:427
msgid "Can't copy Shader. Couldn't retrieve face."
msgstr "Konnte Face nicht casten, Shader wurde nicht kopiert."
-#: ..\..\radiant\selection\algorithm\Shader.cpp:404
+#: ..\..\radiant\selection\algorithm\Shader.cpp:433
msgid "Can't copy Shader. Please select a single face or patch."
msgstr "Shader nicht kopiert: bitte ein einzelnes Face oder einen Patch auswählen."
-#: ..\..\radiant\selection\algorithm\Transformation.cpp:55
+#: ..\..\radiant\selection\algorithm\Transformation.cpp:56
msgid "Cannot scale by zero value."
msgstr "Kann nicht mit 0 skalieren."
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:81
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:97
+msgid "Ungroup Selection"
+msgstr "Gruppierung auflösen"
+
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:84
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:91
+msgid "Group Selection"
+msgstr "Gruppe erstellen"
+
#: ..\..\radiant\selection\ManipulateMouseTool.cpp:28
msgid "Manipulate"
msgstr "Manipulieren"
@@ -644,32 +708,32 @@ msgstr "Manipulieren"
msgid "Select"
msgstr "Auswählen"
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:168
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:175
#: xml_file_content.cpp:4
msgid "Select Faces"
msgstr "Faces auswählen"
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:187
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:194
msgid "Cycle Selection"
msgstr "Auswahl durchrotieren"
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:233
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:247
msgid "Cycle Face Selection"
msgstr "Face-Auswahl durchrotieren"
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:84
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:104
msgid "Selection Set: "
msgstr "Auswahlsatz: "
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:92
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:112
msgid "Clear Selection Sets"
msgstr "Auswahlsätze löschen"
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:194
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:214
msgid "Delete all selection sets?"
msgstr "Alle Auswahlsätze löschen?"
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:195
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:215
msgid ""
"This will delete all set definitions. The actual map objects will not be affected by this step.\n"
"\n"
@@ -701,20 +765,24 @@ msgstr "Kann Auswahlsatz nicht erstellen"
msgid "Cannot create a selection set, there is nothing selected in the current scene."
msgstr "Kann Auswahlsatz nicht anlegen, keine Auswahl vorhanden."
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:87
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:24
+msgid "The name of the shader in the clipboard"
+msgstr "Der Name des Shaders in der Zwischenablage"
+
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:91
#, c-format
msgid "ShaderClipboard: %s"
msgstr "Shader-Zwischenablage: %s"
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:90
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:94
msgid "Face"
msgstr "Face"
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:93
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:97
msgid "Patch"
msgstr "Patch"
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:96
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
#: ..\..\radiant\ui\common\ShaderSelector.cpp:359
#: ..\..\radiant\ui\common\TexturePreviewCombo.cpp:73
#: ..\..\radiant\ui\mapinfo\ShaderInfoTab.cpp:60
@@ -723,7 +791,7 @@ msgstr "Patch"
msgid "Shader"
msgstr "Shader"
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:104
msgid "ShaderClipboard is empty."
msgstr "Shader-Zwischenablage ist leer."
@@ -1524,10 +1592,35 @@ msgstr "Chinesisch"
msgid "Zulu"
msgstr "Zulu"
+#: ..\..\radiant\settings\PreferencePage.cpp:19
+#, c-format
+msgid "%s Settings"
+msgstr "%s Einstellungen"
+
#: ..\..\radiant\textool\TexTool.cpp:38
msgid "Texture Tool"
msgstr "Textur-Werkzeug"
+#: ..\..\radiant\ui\aas\AasControl.cpp:36
+msgid "Reload AAS File"
+msgstr "AAS File neu laden"
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:30
+msgid "AAS Viewer"
+msgstr "AAS Visualisierung"
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:80
+msgid "Search for AAS Files"
+msgstr "Suche AAS Files"
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:84
+msgid "Show Area Numbers"
+msgstr "AAS-Nummern anzeigen"
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:87
+msgid "Hide distant Areas"
+msgstr "Weit entfernte ausblenden"
+
#: ..\..\radiant\ui\about\AboutDialog.cpp:24
msgid "About DarkRadiant"
msgstr "Über DarkRadiant"
@@ -1558,7 +1651,7 @@ msgid "Renderer: %s"
msgstr "Renderer: %s"
#: ..\..\radiant\ui\animationpreview\MD5AnimationViewer.cpp:16
-#: xml_file_content.cpp:139
+#: xml_file_content.cpp:140
msgid "MD5 Animation Viewer"
msgstr "MD5-Animationsvorschau"
@@ -1593,7 +1686,7 @@ msgid "Shortcut List"
msgstr "Liste der Tastenkombinationen"
#: ..\..\radiant\ui\commandlist\CommandList.cpp:53
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:94
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:116
#: xml_file_content.cpp:2
msgid "Command"
msgstr "Befehl"
@@ -1682,7 +1775,7 @@ msgstr "Shaderdefinition ansehen"
#: ..\..\radiant\ui\common\ShaderSelector.cpp:195
#: ..\..\radiant\ui\common\ShaderSelector.cpp:225
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:437
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:481
#: ..\..\plugins\eclasstree\EClassTree.cpp:143
#: ..\..\libs\wxutil\KeyValueTable.cpp:44
msgid "Value"
@@ -1731,7 +1824,7 @@ msgstr "Soundshader"
#: ..\..\radiant\ui\common\SoundChooser.cpp:189
#: ..\..\radiant\ui\entitychooser\EntityClassChooser.cpp:290
#: ..\..\radiant\ui\modelselector\ModelSelector.cpp:340
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:380
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:396
msgid "Loading..."
msgstr "Lade..."
@@ -1764,12 +1857,12 @@ msgid "Custom properties defined for this entity class, if any"
msgstr "Benutzerdefinierte Eigenschaften dieser Entityklasse, falls definiert"
#: ..\..\radiant\ui\einspector\AddPropertyDialog.cpp:76
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:432
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:476
#: ..\..\plugins\eclasstree\EClassTree.cpp:140
msgid "Property"
msgstr "Eigenschaft"
-#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:25
+#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:26
msgid "Choose entity class..."
msgstr "Entityklasse auswählen"
@@ -1781,41 +1874,42 @@ msgstr "Zeige vererbte Eigenschaften"
msgid "Show help"
msgstr "Zeige Hilfe"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:292
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:312
msgid "Add property..."
msgstr "Eigenschaft hinzufügen..."
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:296
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:317
msgid "Delete property"
msgstr "Eigenschaft entfernen"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:304
-msgid "Copy Spawnarg"
-msgstr "Wertepaar kopieren"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:325
+msgid "Copy Spawnarg(s)"
+msgstr "Wertepaar(e) kopieren"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:309
-msgid "Cut Spawnarg"
-msgstr "Wertepaar ausschneiden"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:330
+msgid "Cut Spawnarg(s)"
+msgstr "Wertepaar(e) ausschneiden"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:314
-msgid "Paste Spawnarg"
-msgstr "Wertepaar einfügen"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:335
+msgid "Paste Spawnarg(s)"
+msgstr "Wertepaar(e) einfügen"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:442
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:347
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:350
+#: ..\..\plugins\uimanager\GroupDialog.cpp:28
+msgid "Entity"
+msgstr "Entity"
+
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:486
msgid "?"
msgstr "?"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:654
-#, c-format
-msgid "The name %s already exists in this map!"
-msgstr "Der Name %s existiert bereits in dieser Map!"
-
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1064
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1200
#, c-format
msgid "Entity %d"
msgstr "Entity %d"
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1076
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1212
#, c-format
msgid "Entity %d, Primitive %d"
msgstr "Entity %d, Primitiv %d"
@@ -1824,7 +1918,7 @@ msgstr "Entity %d, Primitiv %d"
msgid "Choose target entity..."
msgstr "Ziel-Entity auswählen..."
-#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:78
+#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:71
#: ..\..\radiant\ui\einspector\Vector3PropertyEditor.cpp:62
msgid "Apply..."
msgstr "Anwenden..."
@@ -2094,59 +2188,53 @@ msgstr "Texturen"
msgid "Window Layout"
msgstr "Fensterlayout"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:93
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:84
msgid "Settings/Multi Monitor"
msgstr "Einstellungen/Multimonitor"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:112
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:103
msgid "Start DarkRadiant on monitor"
msgstr "Starte DarkRadiant auf Monitor"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:131
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:122
msgid "Settings/Compatibility"
msgstr "Einstellungen/Kompatibilität"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:133
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:124
msgid "Disable Windows Desktop Composition"
msgstr "Desktopgestaltung deaktivieren"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:267
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:256
msgid "Exit DarkRadiant"
msgstr "DarkRadiant beenden"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:380
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:383
-#: ..\..\plugins\uimanager\GroupDialog.cpp:28
-msgid "Entity"
-msgstr "Entity"
-
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:391
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:394
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:369
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:372
msgid "Media"
msgstr "Media"
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:402
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:405
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:381
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:384
msgid "Console"
msgstr "Konsole"
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:144
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:145
msgid "Camera Position"
msgstr "Kamera-Position"
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:147
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:148
msgid "Top Left"
msgstr "Oben links"
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:149
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:150
msgid "Top Right"
msgstr "Oben rechts"
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:151
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:152
msgid "Bottom Left"
msgstr "Unten links"
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:153
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:154
msgid "Bottom Right"
msgstr "Unten rechts"
@@ -2450,7 +2538,7 @@ msgid "Merge Entities"
msgstr "Entities zusammenführen"
#: ..\..\radiant\ui\ortho\OrthoContextMenu.cpp:74
-#: xml_file_content.cpp:155
+#: xml_file_content.cpp:156
msgid "Make Visportal"
msgstr "Erzeuge Visportal"
@@ -2524,7 +2612,7 @@ msgid "Patch Inspector"
msgstr "Patch Inspector"
#: ..\..\radiant\ui\patch\PatchInspector.cpp:29
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:55
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:56
#: ..\..\radiant\ui\transform\TransformDialog.cpp:38
msgid "Step:"
msgstr "Schritt:"
@@ -2533,135 +2621,139 @@ msgstr "Schritt:"
msgid "Patch Thicken"
msgstr "Patch-Extrusion"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:41
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:42
msgid "Choose Prefab"
msgstr "Prefab wählen"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:97
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:100
msgid "Rescan Prefab Folders"
msgstr "Prefab-Ordner neu durchsuchen"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:128
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:105
+msgid "Create Group out of Prefab parts"
+msgstr "Eine Gruppe aus diesem Prefab erstellen"
+
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:140
msgid "Browse mod resources"
msgstr "Mod-Ressourcen durchsuchen"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:131
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:143
msgid "Select recently used path:"
msgstr "Zuletzt geöffneten Pfad auswählen:"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:133
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:145
msgid "Browse custom path:"
msgstr "Pfad durchsuchen:"
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:532
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:553
msgid "<no description>"
msgstr "<keine Beschreibung>"
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:37
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:23
msgid "DarkRadiant Preferences"
msgstr "DarkRadiant Einstellungen"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:38
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
msgid "Surface Inspector"
msgstr "Surface Inspector"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
msgid "Texture Properties"
msgstr "Textureigenschaften"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:41
msgid "Texture Operations"
msgstr "Texturoperationen"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:48
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
msgid "Horiz. Shift:"
msgstr "Horiz. Verschiebung:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
msgid "Vert. Shift:"
msgstr "Vert. Verschiebung:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
msgid "Horiz. Scale:"
msgstr "Horiz. Skalierung:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
msgid "Vert. Scale:"
msgstr "Vert. Skalierung:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
msgid "Rotation:"
msgstr "Rotation:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:54
#: xml_file_content.cpp:15
msgid "Shader:"
msgstr "Shader:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:57
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
msgid "Fit Texture:"
msgstr "Texture einpassen:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:59
msgid "Fit"
msgstr "Einpassen"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:60
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
msgid "Align Texture:"
msgstr "Textur ausrichten:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
msgid "Top"
msgstr "Oben"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
msgid "Bottom"
msgstr "Unten"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
#: xml_file_content.cpp:16
msgid "Right"
msgstr "Rechts"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:65
#: xml_file_content.cpp:15
msgid "Left"
msgstr "Links"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:66
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
msgid "Flip Texture:"
msgstr "Textur kippen:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
msgid "Flip Horizontal"
msgstr "Horizonal kippen"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:69
msgid "Flip Vertical"
msgstr "Vertikal kippen"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:70
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
msgid "Modify Texture:"
msgstr "Texturierung bearbeiten:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
msgid "Natural"
msgstr "Natürliche Skala"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:73
msgid "Normalise"
msgstr "Normalisieren"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:74
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
msgid "Default Scale:"
msgstr "Standardskalierung:"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:76
#: xml_file_content.cpp:9
msgid "Texture Lock"
msgstr "Textur-Lock"
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:634
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:649
msgid "Both fit values must be > 0."
msgstr "Beide Fit-Werte müssen größer als 0 sein."
@@ -2670,7 +2762,7 @@ msgid "Seek in Media Browser"
msgstr "In Media Browser zeigen"
#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:269
-#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:811
+#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:809
msgid "No shader"
msgstr "Kein Shader"
@@ -2771,7 +2863,7 @@ msgid "Show Entity Names"
msgstr "Zeige Namen der Entities"
#: ..\..\radiant\xyview\GlobalXYWnd.cpp:205
-#: xml_file_content.cpp:79
+#: xml_file_content.cpp:80
msgid "Show Blocks"
msgstr "Zeige Blöcke"
@@ -2780,17 +2872,17 @@ msgid "Show Coordinates"
msgstr "Zeige Koordinaten"
#: ..\..\radiant\xyview\GlobalXYWnd.cpp:207
-#: xml_file_content.cpp:82
+#: xml_file_content.cpp:83
msgid "Show Axes"
msgstr "Zeige Achsen"
#: ..\..\radiant\xyview\GlobalXYWnd.cpp:208
-#: xml_file_content.cpp:81
+#: xml_file_content.cpp:82
msgid "Show Window Outline"
msgstr "Zeige Fensterumrandung"
#: ..\..\radiant\xyview\GlobalXYWnd.cpp:209
-#: xml_file_content.cpp:83
+#: xml_file_content.cpp:84
msgid "Show Workzone"
msgstr "Zeige Arbeitsbereich"
@@ -2802,6 +2894,10 @@ msgstr "Translationen sind immer achsengebunden"
msgid "Higher Selection Priority for Entities"
msgstr "Höhere Auswahlpriorität für Entities"
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:665
+msgid "Shows the mouse position in the orthoview"
+msgstr "Zeigt die aktuelle Position des Mauszeigers in der Ortho-Ansicht"
+
#: ..\..\radiant\xyview\tools\BrushCreatorTool.cpp:25
msgid "Drag-create Brush"
msgstr "Erzeuge neue Brush"
@@ -2815,7 +2911,7 @@ msgid "Drag Camera"
msgstr "Kamera verschieben"
#: ..\..\radiant\xyview\tools\ClipperTool.cpp:21
-#: xml_file_content.cpp:149
+#: xml_file_content.cpp:150
#: xml_file_content.cpp:12
#: xml_file_content.cpp:17
msgid "Clipper"
@@ -2841,7 +2937,7 @@ msgstr "XZ Vorne"
msgid "YZ Side"
msgstr "YZ Seite"
-#: ..\..\radiant\xyview\XYWnd.cpp:637
+#: ..\..\radiant\xyview\XYWnd.cpp:498
#, c-format
msgid "x: %6.1lf y: %6.1lf z: %6.1lf"
msgstr "x: %6.1lf y: %6.1lf z: %6.1lf"
@@ -2860,7 +2956,7 @@ msgstr "Befehl bearbeiten"
msgid "Conversation Editor"
msgstr "Konversations-Editor"
-#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:278
+#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:280
#, c-format
msgid "Unable to create conversation Entity: class '%s' not found."
msgstr "Kann Konversationsentity nicht anlegen, Klasse '%s' nicht gefunden."
@@ -2869,35 +2965,35 @@ msgstr "Kann Konversationsentity nicht anlegen, Klasse '%s' nicht gefunden."
msgid "Edit Conversation"
msgstr "Konversation bearbeiten"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:67
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:89
msgid "Actor (click to edit)"
msgstr "Akteur (zum Bearbeiten klicken)"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:92
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:114
#: xml_file_content.cpp:1
msgid "Actor"
msgstr "Akteur"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:96
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:118
msgid "Wait"
msgstr "Warten"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:201
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:223
#, c-format
msgid "Actor %d"
msgstr "Akteur %d"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "yes"
msgstr "Ja"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "no"
msgstr "Nein"
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:369
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:394
msgid "New Actor"
msgstr "Neuer Akteur"
@@ -4025,7 +4121,7 @@ msgstr "Entfernen"
#: ..\..\plugins\dm.stimresponse\ResponseEditor.cpp:412
#: ..\..\plugins\dm.stimresponse\StimEditor.cpp:403
#: ..\..\plugins\uimanager\colourscheme\ColourSchemeEditor.cpp:95
-#: xml_file_content.cpp:179
+#: xml_file_content.cpp:180
#: xml_file_content.cpp:3
#: xml_file_content.cpp:7
#: xml_file_content.cpp:9
@@ -4171,7 +4267,8 @@ msgstr "Responses"
msgid "Custom Stims"
msgstr "Benutzerdefinierte Stims"
-#: ..\..\plugins\eclassmgr\EClassManager.cpp:330
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:327
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:328
msgid "Reloading Defs"
msgstr "Neuladen der Definitionen"
@@ -4217,47 +4314,51 @@ msgstr "Unbekannt"
msgid "All Files"
msgstr "Alle Dateien"
-#: ..\..\plugins\grid\Grid.cpp:151
+#: ..\..\plugins\grid\Grid.cpp:55
+msgid "Current Grid Size"
+msgstr "Aktuelle Rastergröße"
+
+#: ..\..\plugins\grid\Grid.cpp:152
msgid "Settings/Grid"
msgstr "Einstellungen/Raster"
-#: ..\..\plugins\grid\Grid.cpp:153
+#: ..\..\plugins\grid\Grid.cpp:154
msgid "Default Grid Size"
msgstr "Standard-Rastergröße"
-#: ..\..\plugins\grid\Grid.cpp:157
+#: ..\..\plugins\grid\Grid.cpp:158
msgid "Lines"
msgstr "Linien"
-#: ..\..\plugins\grid\Grid.cpp:158
+#: ..\..\plugins\grid\Grid.cpp:159
msgid "Dotted Lines"
msgstr "Gepunktete Linien"
-#: ..\..\plugins\grid\Grid.cpp:159
+#: ..\..\plugins\grid\Grid.cpp:160
msgid "More Dotted Lines"
msgstr "Stärker gepunktete Linien"
-#: ..\..\plugins\grid\Grid.cpp:160
+#: ..\..\plugins\grid\Grid.cpp:161
msgid "Crosses"
msgstr "Kreuze"
-#: ..\..\plugins\grid\Grid.cpp:161
+#: ..\..\plugins\grid\Grid.cpp:162
msgid "Dots"
msgstr "Punkte"
-#: ..\..\plugins\grid\Grid.cpp:162
+#: ..\..\plugins\grid\Grid.cpp:163
msgid "Big Dots"
msgstr "Große Punkte"
-#: ..\..\plugins\grid\Grid.cpp:163
+#: ..\..\plugins\grid\Grid.cpp:164
msgid "Squares"
msgstr "Quadrate"
-#: ..\..\plugins\grid\Grid.cpp:165
+#: ..\..\plugins\grid\Grid.cpp:166
msgid "Major Grid Style"
msgstr "Hauptgitter-Stil"
-#: ..\..\plugins\grid\Grid.cpp:166
+#: ..\..\plugins\grid\Grid.cpp:167
msgid "Minor Grid Style"
msgstr "Nebengitter-Stil"
@@ -4288,24 +4389,25 @@ msgid "Incorrect map version: required %f, found %f"
msgstr "Ungültige Map-Version: erwartet: %f, gefunden: %f"
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:144
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:94
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:102
#, c-format
msgid "Primitive #%d: parse error"
msgstr "Primitiv #%d: Parserfehler"
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:154
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:104
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:112
#, c-format
msgid "Primitive #%d: parse exception %s"
msgstr "Primitiv #%d: Parserfehler %s"
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:245
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:195
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:203
#, c-format
msgid "Parsed invalid value '%s' for key '%s'"
msgstr "Ungültigen Wert '%s' für Schlüssel '%s' eingelesen"
#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:125
+#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:234
#, c-format
msgid "BrushDefParser: invalid token '%s'"
msgstr "BrushDefParser: Ungültiges Token '%s'"
@@ -4377,23 +4479,23 @@ msgstr "Partikeleditor..."
msgid "Cannot save particle, it has not been registered yet."
msgstr "Kann Partikeldefinition nicht speichern, sie wurde nicht registriert."
-#: ..\..\plugins\particles\ParticlesManager.cpp:316
-#: ..\..\plugins\particles\ParticlesManager.cpp:344
+#: ..\..\plugins\particles\ParticlesManager.cpp:325
+#: ..\..\plugins\particles\ParticlesManager.cpp:353
#, c-format
msgid "Cannot open file for writing: %s"
msgstr "Kann die Datei nicht im Schreibmodus öffnen: %s"
-#: ..\..\plugins\particles\ParticlesManager.cpp:357
+#: ..\..\plugins\particles\ParticlesManager.cpp:366
#, c-format
msgid "Cannot open file for reading: %s"
msgstr "Kann die Datei nicht im Lesemodus öffnen: %s"
-#: ..\..\plugins\particles\ParticlesManager.cpp:404
+#: ..\..\plugins\particles\ParticlesManager.cpp:413
#, c-format
msgid "Could not remove the file %s"
msgstr "Kann die Datei nicht entfernen: %s"
-#: ..\..\plugins\particles\ParticlesManager.cpp:418
+#: ..\..\plugins\particles\ParticlesManager.cpp:427
#, c-format
msgid "Could not rename the temporary file %s"
msgstr "Konnte die temporäre Datei nicht entfernen: %s"
@@ -4407,7 +4509,7 @@ msgstr "Skript"
msgid "Reload Scripts"
msgstr "Skripts neu laden"
-#: ..\..\plugins\script\ScriptMenu.cpp:51
+#: ..\..\plugins\script\ScriptMenu.cpp:60
msgid "No scripts available"
msgstr "Keine Skripts verfügbar"
@@ -4419,7 +4521,7 @@ msgstr "Python Skripteingabe"
msgid "Run Script"
msgstr "Starte Skript"
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Loading Shaders"
msgstr "Lade Shader"
@@ -4458,22 +4560,18 @@ msgstr "Es existiert bereits ein Schema mit diesem Namen."
msgid "_Filters"
msgstr "_Filter"
-#: ..\..\plugins\undo\UndoSystem.cpp:384
+#: ..\..\plugins\uimanager\UIManager.cpp:115
+msgid "Describes available Mouse Commands"
+msgstr "Listet verfügbare Mauskommandos auf"
+
+#: ..\..\plugins\undo\UndoSystem.cpp:398
msgid "Settings/Undo System"
msgstr "Einstellungen/Undo"
-#: ..\..\plugins\undo\UndoSystem.cpp:385
+#: ..\..\plugins\undo\UndoSystem.cpp:399
msgid "Undo Queue Size"
msgstr "Größe des Undo-Stapels"
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:31
-msgid "Save as Obj"
-msgstr "Als OBJ speichern"
-
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:89
-msgid "Export Selection as OBJ..."
-msgstr "Auswahl als OBJ exportieren..."
-
#: ..\..\libs\wxutil\dialog\MessageBox.cpp:20
#: xml_file_content.cpp:8
#: xml_file_content.cpp:10
@@ -4617,7 +4715,7 @@ msgid "Reload S&kins"
msgstr "S&kins neu laden"
#: xml_file_content.cpp:16
-#: xml_file_content.cpp:26
+#: xml_file_content.cpp:28
msgid "Reload Materials"
msgstr "Materials neu laden"
@@ -4777,501 +4875,501 @@ msgstr "Patch Inspector"
msgid "&Texture Tool"
msgstr "Textur-Werkzeug"
-#: xml_file_content.cpp:61
+#: xml_file_content.cpp:60
+msgid "AAS Area Viewer"
+msgstr "AAS Visualisierung"
+
+#: xml_file_content.cpp:62
msgid "&Center"
msgstr "Zentrieren"
-#: xml_file_content.cpp:62
+#: xml_file_content.cpp:63
msgid "&Up Floor"
msgstr "Ein Stockwerk höher"
-#: xml_file_content.cpp:63
+#: xml_file_content.cpp:64
msgid "&Down Floor"
msgstr "Ein Stockwerk tiefer"
-#: xml_file_content.cpp:64
+#: xml_file_content.cpp:65
msgid "Far Clip Plane In"
msgstr "Entfernte Clip-Ebene heran"
-#: xml_file_content.cpp:65
+#: xml_file_content.cpp:66
msgid "Far Clip Plane Out"
msgstr "Entfernte Clip-Ebene hinaus"
-#: xml_file_content.cpp:66
+#: xml_file_content.cpp:67
msgid "Next leak spot"
msgstr "Nächster Leak-Spot"
-#: xml_file_content.cpp:67
+#: xml_file_content.cpp:68
msgid "Previous leak spot"
msgstr "Vorheriger Leak-Spot"
-#: xml_file_content.cpp:68
+#: xml_file_content.cpp:69
msgid "Orthographic"
msgstr "2D-Ansicht"
-#: xml_file_content.cpp:69
+#: xml_file_content.cpp:70
msgid "Next (XY, XZ, YZ)"
msgstr "Nächste Ansicht (XY, XZ, YZ)"
-#: xml_file_content.cpp:70
+#: xml_file_content.cpp:71
msgid "XY (Top)"
msgstr "XY (Oben)"
-#: xml_file_content.cpp:71
+#: xml_file_content.cpp:72
msgid "YZ"
msgstr "YZ"
-#: xml_file_content.cpp:72
+#: xml_file_content.cpp:73
msgid "XZ"
msgstr "XZ"
-#: xml_file_content.cpp:73
+#: xml_file_content.cpp:74
msgid "&XY 100%"
msgstr "XY 100%"
-#: xml_file_content.cpp:74
+#: xml_file_content.cpp:75
msgid "&XY Zoom In"
msgstr "XY Einzoomen"
-#: xml_file_content.cpp:75
+#: xml_file_content.cpp:76
msgid "&XY Zoom Out"
msgstr "XY Auszoomen"
-#: xml_file_content.cpp:76
+#: xml_file_content.cpp:77
msgid "Show"
msgstr "Zeigen"
-#: xml_file_content.cpp:77
+#: xml_file_content.cpp:78
msgid "Show &Angles"
msgstr "Zeige Winkel"
-#: xml_file_content.cpp:78
+#: xml_file_content.cpp:79
msgid "Show &Names"
msgstr "Zeige Namen"
-#: xml_file_content.cpp:80
+#: xml_file_content.cpp:81
msgid "Show C&oordinates"
msgstr "Zeige Koordinaten"
-#: xml_file_content.cpp:84
+#: xml_file_content.cpp:85
msgid "Show size info"
msgstr "Zeige Größeninformation"
-#: xml_file_content.cpp:85
+#: xml_file_content.cpp:86
msgid "Hide/Show"
msgstr "Verbergen/Zeigen"
-#: xml_file_content.cpp:86
+#: xml_file_content.cpp:87
msgid "Hide Selected"
msgstr "Auswahl verbergen"
-#: xml_file_content.cpp:87
+#: xml_file_content.cpp:88
msgid "Hide Deselected"
msgstr "Nicht ausgewähltes verbergen"
-#: xml_file_content.cpp:88
+#: xml_file_content.cpp:89
msgid "Show hidden"
msgstr "Zeige Verborgenes"
-#: xml_file_content.cpp:90
+#: xml_file_content.cpp:91
msgid "&Switch off"
msgstr "Ausschalten"
-#: xml_file_content.cpp:91
+#: xml_file_content.cpp:92
msgid "Set from &XY view"
msgstr "Über XY-Ansicht festlegen"
-#: xml_file_content.cpp:92
+#: xml_file_content.cpp:93
msgid "Set from &Brush"
msgstr "Über Brush festlegen"
-#: xml_file_content.cpp:93
+#: xml_file_content.cpp:94
msgid "Set from Se&lection"
msgstr "Über Auswahl festlegen"
-#: xml_file_content.cpp:94
+#: xml_file_content.cpp:95
msgid "Colours..."
msgstr "Farben..."
-#: xml_file_content.cpp:95
+#: xml_file_content.cpp:96
msgid "Background Image..."
msgstr "Hintergrundbild..."
-#: xml_file_content.cpp:96
+#: xml_file_content.cpp:97
msgid "Mo&dify"
msgstr "Komponentenmodus"
-#: xml_file_content.cpp:97
+#: xml_file_content.cpp:98
#: xml_file_content.cpp:16
msgid "Components"
msgstr "Komponenten"
-#: xml_file_content.cpp:98
+#: xml_file_content.cpp:99
msgid "&Edges"
msgstr "Edges"
-#: xml_file_content.cpp:99
+#: xml_file_content.cpp:100
msgid "&Vertices"
msgstr "Vertices"
-#: xml_file_content.cpp:100
+#: xml_file_content.cpp:101
msgid "&Faces"
msgstr "Faces"
-#: xml_file_content.cpp:101
+#: xml_file_content.cpp:102
msgid "En&tities"
msgstr "Entities"
-#: xml_file_content.cpp:102
+#: xml_file_content.cpp:103
msgid "Nudge"
msgstr "Verschieben"
-#: xml_file_content.cpp:103
+#: xml_file_content.cpp:104
msgid "Nudge Left"
msgstr "Verschiebe nach links"
-#: xml_file_content.cpp:104
+#: xml_file_content.cpp:105
msgid "Nudge Right"
msgstr "Verschiebe nach rechts"
-#: xml_file_content.cpp:105
+#: xml_file_content.cpp:106
msgid "Nudge Up"
msgstr "Verschiebe nach oben"
-#: xml_file_content.cpp:106
+#: xml_file_content.cpp:107
msgid "Nudge Down"
msgstr "Verschiebe nach unten"
-#: xml_file_content.cpp:107
+#: xml_file_content.cpp:108
#: xml_file_content.cpp:15
msgid "Rotate"
msgstr "Drehen"
-#: xml_file_content.cpp:108
+#: xml_file_content.cpp:109
msgid "Rotate X"
msgstr "Drehe um X-Achse"
-#: xml_file_content.cpp:109
+#: xml_file_content.cpp:110
msgid "Rotate Y"
msgstr "Drehe um Y-Achse"
-#: xml_file_content.cpp:110
+#: xml_file_content.cpp:111
msgid "Rotate Z"
msgstr "Drehe um Z-Achse"
-#: xml_file_content.cpp:111
+#: xml_file_content.cpp:112
msgid "Mirror"
msgstr "Spiegeln"
-#: xml_file_content.cpp:112
+#: xml_file_content.cpp:113
msgid "Mirror &X"
msgstr "Spiegeln um X-Achse"
-#: xml_file_content.cpp:113
+#: xml_file_content.cpp:114
msgid "Mirror &Y"
msgstr "Spiegeln um Y-Achse"
-#: xml_file_content.cpp:114
+#: xml_file_content.cpp:115
msgid "Mirror &Z"
msgstr "Spiegeln um Z-Achse"
-#: xml_file_content.cpp:115
+#: xml_file_content.cpp:116
#: xml_file_content.cpp:10
msgid "Rotate Objects independently"
msgstr "Objekte unabhängig voneinander drehen"
-#: xml_file_content.cpp:116
+#: xml_file_content.cpp:117
msgid "Rotate and scale..."
msgstr "Drehen und skalieren..."
-#: xml_file_content.cpp:117
+#: xml_file_content.cpp:118
msgid "&Grid"
msgstr "Raster"
-#: xml_file_content.cpp:118
+#: xml_file_content.cpp:119
msgid "Snap selected to grid"
msgstr "Auswahl am Raster ausrichten"
-#: xml_file_content.cpp:119
+#: xml_file_content.cpp:120
msgid "Grid0.125"
msgstr "Grid0.125"
-#: xml_file_content.cpp:120
+#: xml_file_content.cpp:121
msgid "Grid0.25"
msgstr "Grid0.25"
-#: xml_file_content.cpp:121
+#: xml_file_content.cpp:122
msgid "Grid0.5"
msgstr "Grid0.5"
-#: xml_file_content.cpp:122
+#: xml_file_content.cpp:123
msgid "Grid1"
msgstr "Grid1"
-#: xml_file_content.cpp:123
+#: xml_file_content.cpp:124
msgid "Grid2"
msgstr "Grid2"
-#: xml_file_content.cpp:124
+#: xml_file_content.cpp:125
msgid "Grid4"
msgstr "Grid4"
-#: xml_file_content.cpp:125
+#: xml_file_content.cpp:126
msgid "Grid8"
msgstr "Grid8"
-#: xml_file_content.cpp:126
+#: xml_file_content.cpp:127
msgid "Grid16"
msgstr "Grid16"
-#: xml_file_content.cpp:127
+#: xml_file_content.cpp:128
msgid "Grid32"
msgstr "Grid32"
-#: xml_file_content.cpp:128
+#: xml_file_content.cpp:129
msgid "Grid64"
msgstr "Grid64"
-#: xml_file_content.cpp:129
+#: xml_file_content.cpp:130
msgid "Grid128"
msgstr "Grid128"
-#: xml_file_content.cpp:130
+#: xml_file_content.cpp:131
msgid "Grid256"
msgstr "Grid256"
-#: xml_file_content.cpp:131
+#: xml_file_content.cpp:132
msgid "M&ap"
msgstr "Map"
-#: xml_file_content.cpp:132
+#: xml_file_content.cpp:133
msgid "Find brush..."
msgstr "Brush suchen..."
-#: xml_file_content.cpp:133
+#: xml_file_content.cpp:134
msgid "Find and replace textures..."
msgstr "Texturen suchen & ersetzen..."
-#: xml_file_content.cpp:134
+#: xml_file_content.cpp:135
msgid "Map info..."
msgstr "Map-Information"
-#: xml_file_content.cpp:135
+#: xml_file_content.cpp:136
msgid "E&ntity"
msgstr "Entity"
-#: xml_file_content.cpp:136
+#: xml_file_content.cpp:137
msgid "&Revert group to worldspawn"
msgstr "Gruppe zu Worldspawn umwandeln"
-#: xml_file_content.cpp:137
+#: xml_file_content.cpp:138
msgid "&Connect selected entities"
msgstr "Ausgewählte Entities verbinden"
-#: xml_file_content.cpp:138
+#: xml_file_content.cpp:139
msgid "&Bind selected entities"
msgstr "Ausgewählte Entities verknüpfen"
-#: xml_file_content.cpp:140
+#: xml_file_content.cpp:141
msgid "B&rush"
msgstr "Brush"
-#: xml_file_content.cpp:141
+#: xml_file_content.cpp:142
msgid "Prism..."
msgstr "Prisma..."
-#: xml_file_content.cpp:142
+#: xml_file_content.cpp:143
msgid "Cone..."
msgstr "Kegel..."
-#: xml_file_content.cpp:143
+#: xml_file_content.cpp:144
msgid "Sphere..."
msgstr "Kugel..."
-#: xml_file_content.cpp:144
+#: xml_file_content.cpp:145
msgid "CSG"
msgstr "CSG"
-#: xml_file_content.cpp:145
+#: xml_file_content.cpp:146
msgid "Make &Hollow"
msgstr "Aushöhlen"
-#: xml_file_content.cpp:146
+#: xml_file_content.cpp:147
msgid "Make &Room"
msgstr "Raum erstellen"
-#: xml_file_content.cpp:147
+#: xml_file_content.cpp:148
msgid "CSG &Subtract"
msgstr "CSG Subtraktion"
-#: xml_file_content.cpp:148
+#: xml_file_content.cpp:149
msgid "CSG &Merge"
msgstr "CSG Zusammenfügen"
-#: xml_file_content.cpp:150
+#: xml_file_content.cpp:151
msgid "Clip Selection"
msgstr "Auswahl clippen"
-#: xml_file_content.cpp:151
+#: xml_file_content.cpp:152
msgid "Split Selection"
msgstr "Auswahl splitten"
-#: xml_file_content.cpp:152
+#: xml_file_content.cpp:153
msgid "Flip Clip Orientation"
msgstr "Clip-Orientierung umkehren"
-#: xml_file_content.cpp:153
+#: xml_file_content.cpp:154
msgid "Texture lock"
msgstr "Textur-Lock"
-#: xml_file_content.cpp:154
+#: xml_file_content.cpp:155
msgid "Create Decal Patches"
msgstr "Decal-Patches erstellen"
-#: xml_file_content.cpp:156
+#: xml_file_content.cpp:157
msgid "Make Detail"
msgstr "Als Detail markieren"
-#: xml_file_content.cpp:157
+#: xml_file_content.cpp:158
msgid "Make Structural"
msgstr "Als Struktur markieren"
-#: xml_file_content.cpp:158
+#: xml_file_content.cpp:159
msgid "&Patch"
msgstr "Patch"
-#: xml_file_content.cpp:159
+#: xml_file_content.cpp:160
msgid "Create Simple Patch Mesh"
msgstr "Neuer einfacher Patch"
-#: xml_file_content.cpp:160
+#: xml_file_content.cpp:161
msgid "Create End cap"
msgstr "Endcap erstellen"
-#: xml_file_content.cpp:161
+#: xml_file_content.cpp:162
msgid "Create Bevel"
msgstr "Bogen erstellen"
-#: xml_file_content.cpp:162
+#: xml_file_content.cpp:163
msgid "Create Cone"
msgstr "Kegel erstellen"
-#: xml_file_content.cpp:163
+#: xml_file_content.cpp:164
msgid "Create Cylinder"
msgstr "Zylinder erstellen"
-#: xml_file_content.cpp:164
+#: xml_file_content.cpp:165
msgid "Create Sphere"
msgstr "Kugel erzeugen"
-#: xml_file_content.cpp:165
+#: xml_file_content.cpp:166
msgid "More cylinders"
msgstr "Mehr Zylinderarten"
-#: xml_file_content.cpp:166
+#: xml_file_content.cpp:167
msgid "Create Dense Cylinder"
msgstr "Erstelle \"dichten\" Zylinder"
-#: xml_file_content.cpp:167
+#: xml_file_content.cpp:168
msgid "Create Very Dense Cylinder"
msgstr "Erstelle \"sehr dichten\" Zylinder"
-#: xml_file_content.cpp:168
+#: xml_file_content.cpp:169
msgid "Create Square Cylinder"
msgstr "Erstelle quadratischen Zylinder"
-#: xml_file_content.cpp:169
+#: xml_file_content.cpp:170
msgid "Insert"
msgstr "Einfügen"
-#: xml_file_content.cpp:170
+#: xml_file_content.cpp:171
msgid "Insert 2 Columns at the beginning"
msgstr "Zwei Spalten am Anfang einfügen"
-#: xml_file_content.cpp:171
+#: xml_file_content.cpp:172
msgid "Insert 2 Columns at the end"
msgstr "Zwei Spalten am Ende einfügen"
-#: xml_file_content.cpp:172
+#: xml_file_content.cpp:173
msgid "Insert 2 Rows at the beginning"
msgstr "Zwei Zeilen am Anfang einfügen"
-#: xml_file_content.cpp:173
+#: xml_file_content.cpp:174
msgid "Insert 2 Rows at the end"
msgstr "Zwei Zeilen am Ende einfügen"
-#: xml_file_content.cpp:174
+#: xml_file_content.cpp:175
msgid "Append"
msgstr "Anfügen"
-#: xml_file_content.cpp:175
+#: xml_file_content.cpp:176
msgid "Append 2 columns at the beginning"
msgstr "Zwei Spalten am Anfang anfügen"
-#: xml_file_content.cpp:176
+#: xml_file_content.cpp:177
msgid "Append 2 columns at the end"
msgstr "Zwei Spalten am Ende anfügen"
-#: xml_file_content.cpp:177
+#: xml_file_content.cpp:178
msgid "Append 2 rows at the beginning"
msgstr "Zwei Zeilen am Anfang anfügen"
-#: xml_file_content.cpp:178
+#: xml_file_content.cpp:179
msgid "Append 2 rows at the end"
msgstr "Zwei Zeilen am Ende anfügen"
-#: xml_file_content.cpp:180
+#: xml_file_content.cpp:181
msgid "Delete 2 columns from the beginning"
msgstr "Zwei Spalten am Anfang löschen"
-#: xml_file_content.cpp:181
+#: xml_file_content.cpp:182
msgid "Delete 2 columns from the end"
msgstr "Zwei Spalten am Ende löschen"
-#: xml_file_content.cpp:182
+#: xml_file_content.cpp:183
msgid "Delete 2 rows from the beginning"
msgstr "Zwei Zeilen am Anfang löschen"
-#: xml_file_content.cpp:183
+#: xml_file_content.cpp:184
msgid "Delete 2 rows from the end"
msgstr "Zwei Spalten am Ende löschen"
-#: xml_file_content.cpp:184
+#: xml_file_content.cpp:185
msgid "Matrix"
msgstr "Matrix"
-#: xml_file_content.cpp:185
+#: xml_file_content.cpp:186
msgid "Invert"
msgstr "Invertieren"
-#: xml_file_content.cpp:186
+#: xml_file_content.cpp:187
msgid "Re-disperse"
msgstr "Neu verteilen"
-#: xml_file_content.cpp:187
+#: xml_file_content.cpp:188
msgid "Rows"
msgstr "Zeilen"
-#: xml_file_content.cpp:188
+#: xml_file_content.cpp:189
msgid "Columns"
msgstr "Spalten"
-#: xml_file_content.cpp:189
+#: xml_file_content.cpp:190
msgid "Transpose"
msgstr "Transponieren"
-#: xml_file_content.cpp:190
+#: xml_file_content.cpp:191
msgid "Thicken Selected Patches"
msgstr "Ausgewählte Patches extrudieren"
-#: xml_file_content.cpp:191
+#: xml_file_content.cpp:192
msgid "Cap Selection"
msgstr "Cap für Auswahl erstellen"
-#: xml_file_content.cpp:192
-msgid "Cycle Cap Texture"
-msgstr "Cap-Textur durchrotieren"
-
#: xml_file_content.cpp:193
msgid "Stitch Patch Textures"
msgstr "Patch-Texturen zusammenfügen"
@@ -5509,58 +5607,66 @@ msgid "Make Room"
msgstr "Raum erstellen"
#: xml_file_content.cpp:20
+msgid "Group selected items"
+msgstr "Ausgewählte Elemente gruppieren"
+
+#: xml_file_content.cpp:21
+msgid "Ungroup selected items"
+msgstr "Gruppierte Elemente auflösen"
+
+#: xml_file_content.cpp:22
msgid "Put caps on the current patch"
msgstr "Cap-Patches für Auswahl erstellen"
-#: xml_file_content.cpp:21
+#: xml_file_content.cpp:23
msgid "Creates a NURBS curve"
msgstr "NURBS-Kurve erstellen"
-#: xml_file_content.cpp:22
+#: xml_file_content.cpp:24
msgid "Convert the selected curve (NURBS <-> CatmullRom)"
msgstr "Konvertiert die ausgewählte Kurve NURBS <-> CatmullRom"
-#: xml_file_content.cpp:23
+#: xml_file_content.cpp:25
msgid "Appends a control point to the selected curves"
msgstr "Einen Kurvenkontrollpunkt zur ausgewählten Kurve hinzufügen"
-#: xml_file_content.cpp:24
+#: xml_file_content.cpp:26
msgid "Inserts a curve control point before the selected ones"
msgstr "Fügt einen Kurvenkontrollpunkt vor dem ausgewählten Punkt ein"
-#: xml_file_content.cpp:25
+#: xml_file_content.cpp:27
msgid "Removes the selected curve control points"
msgstr "Ausgewählte Kurvenkontrollpunkte entfernen"
-#: xml_file_content.cpp:27
+#: xml_file_content.cpp:29
msgid "Find & Replace"
msgstr "Suchen & Ersetzen"
-#: xml_file_content.cpp:28
+#: xml_file_content.cpp:30
msgid "Decrease Grid Size"
msgstr "Rastergröße verkleinern"
-#: xml_file_content.cpp:29
+#: xml_file_content.cpp:31
msgid "Increase Grid Size"
msgstr "Rastergröße vergrößern"
-#: xml_file_content.cpp:30
+#: xml_file_content.cpp:32
msgid "Snap to Grid"
msgstr "Am Raster ausrichten"
-#: xml_file_content.cpp:31
+#: xml_file_content.cpp:33
msgid "Merge Selection"
msgstr "Auswahl zusammenführen"
-#: xml_file_content.cpp:32
+#: xml_file_content.cpp:34
msgid "Flip Selection Horiz (S-Axis)"
msgstr "Auswahl Horizontal kippen (S-Achse)"
-#: xml_file_content.cpp:33
+#: xml_file_content.cpp:35
msgid "Flip Selection Vertical (T-Axis)"
msgstr "Auswahl vertikal kippen (T-Achse)"
-#: xml_file_content.cpp:34
+#: xml_file_content.cpp:36
msgid "Select Related Items"
msgstr "Verbundene Objekte auswählen"
@@ -6626,6 +6732,15 @@ msgstr "Min:"
msgid "Max:"
msgstr "Max:"
+#~ msgid "Cycle Cap Texture"
+#~ msgstr "Cap-Textur durchrotieren"
+
+#~ msgid "Save as Obj"
+#~ msgstr "Als OBJ speichern"
+
+#~ msgid "Export Selection as OBJ..."
+#~ msgstr "Auswahl als OBJ exportieren..."
+
#~ msgid "Loading models"
#~ msgstr "Lade Modelle"
diff --git a/install/input.xml b/install/input.xml
index 14a9adb..f517d29 100644
--- a/install/input.xml
+++ b/install/input.xml
@@ -17,6 +17,7 @@
<mouseToolMapping name="CameraView" id="1">
<tool name="FreeMoveTool" button="RMB" modifiers="" />
<tool name="JumpToObjectTool" button="RMB" modifiers="ALT" />
+ <tool name="PanViewTool" button="RMB" modifiers="CONTROL" />
<tool name="PickShaderTool" button="MMB" modifiers="" />
<tool name="PasteShaderProjectedTool" button="MMB" modifiers="CONTROL" />
<tool name="PasteShaderNaturalTool" button="MMB" modifiers="SHIFT" />
@@ -127,7 +128,6 @@
<shortcut command="RedisperseCols" key="E" modifiers="SHIFT+CONTROL" />
<shortcut command="MatrixTranspose" key="M" modifiers="SHIFT+CONTROL" />
<shortcut command="CapCurrentCurve" key="C" modifiers="SHIFT" />
- <shortcut command="CycleCapTexturePatch" key="N" modifiers="SHIFT+CONTROL" />
<shortcut command="NextLeakSpot" key="K" modifiers="SHIFT+CONTROL" />
<shortcut command="PrevLeakSpot" key="L" modifiers="SHIFT+CONTROL" />
<shortcut command="SurfaceInspector" key="S" />
@@ -169,7 +169,6 @@
<shortcut command="NormaliseTexture" key="" modifiers=""/>
<shortcut command="TexToolGridUp" key="plus" modifiers="SHIFT" />
<shortcut command="TexToolGridDown" key="minus" modifiers="SHIFT" />
- <shortcut command="TexToolSnapToGrid" key="G" modifiers="CONTROL+SHIFT" />
<shortcut command="TexToolMergeItems" key="M" modifiers="ALT" />
<shortcut command="GroupCycleBackward" key="ISO_Left_Tab" modifiers="SHIFT"/>
<shortcut command="GroupCycleForward" key="Tab" modifiers=""/>
@@ -196,5 +195,8 @@
<shortcut command="LoadPosition9" key="9" modifiers="ALT"/>
<shortcut command="OverlayDialog" key="O" modifiers="ALT"/>
<shortcut command="ToggleRotationPivot" key="R" modifiers="CONTROL" />
+ <shortcut command="ToggleAasControlDialog" key="A" modifiers="CONTROL+SHIFT" />
+ <shortcut command="GroupSelected" key="G" modifiers="CONTROL+SHIFT" />
+ <shortcut command="UngroupSelected" key="U" modifiers="CONTROL+SHIFT" />
</shortcuts>
</input>
diff --git a/install/menu.xml b/install/menu.xml
index 042277b..22c5c2f 100644
--- a/install/menu.xml
+++ b/install/menu.xml
@@ -76,6 +76,7 @@
<menuItem name="patchinspector" caption="&Patch Inspector" command="PatchInspector" />
<menuItem name="texturetool" caption="&Texture Tool" command="TextureTool" />
<menuItem name="entityList" caption="Entity List" command="EntityList" />
+ <menuItem name="aasDialog" caption="AAS Area Viewer" command="ToggleAasControlDialog" />
<menuSeparator />
<subMenu name="camera" caption="Camera">
@@ -293,7 +294,6 @@
<menuSeparator />
<menuItem name="thickenPatches" caption="Thicken Selected Patches" command="ThickenPatch" />
<menuItem name="capselection" caption="Cap Selection" command="CapCurrentCurve" icon="curve_cap.png" />
- <menuItem name="cycleCapTexture" caption="Cycle Cap Texture" command="CycleCapTexturePatch" />
<menuSeparator />
<menuItem name="stitchTextures" caption="Stitch Patch Textures" command="StitchPatchTexture" />
<menuItem name="bulgePatch" caption="Bulge patch" command="BulgePatch" />
diff --git a/install/scripts/commands/check_for_invalid_visportals.py b/install/scripts/commands/check_for_invalid_visportals.py
new file mode 100644
index 0000000..7641eb4
--- /dev/null
+++ b/install/scripts/commands/check_for_invalid_visportals.py
@@ -0,0 +1,69 @@
+"""Find any visportal brushes in the map with more than exactly one
+ face assigned to the textures/editor/visportal shader.
+
+Tracker item: #4397 (http://bugs.thedarkmod.com/view.php?id=4397)
+Author: greebo
+Version: 1.0
+"""
+
+__commandName__ = 'check_invalid_visportals' # should not contain spaces
+__commandDisplayName__ = 'Test for invalid Visportals '
+
+def execute():
+
+ # Returns 1 if the brush is a valid visportal, 0 otherwise
+ def testVisportalBrush(brush, visportalShader):
+ numVisportalFaces = 0
+
+ for index in range(brush.getNumFaces()):
+ if brush.getFace(index).getShader() == visportalShader:
+ numVisportalFaces += 1
+
+ if numVisportalFaces != 1:
+ return 0 # brush is not OK
+
+ return 1 # brush is ok
+
+ class VisportalResults(object):
+ numVisportals = 0
+ invalidPortals = []
+
+ results = VisportalResults()
+ visportalShader = 'textures/editor/visportal'
+
+ class VisportalChecker(SceneNodeVisitor):
+ def pre(self, node):
+ if node.isBrush():
+ brush = node.getBrush()
+ if brush.hasShader(visportalShader):
+ results.numVisportals += 1
+
+ if not testVisportalBrush(brush, visportalShader):
+ results.invalidPortals.append(brush)
+ return 0 # don't traverse brushes
+ return 1
+
+ # Instantiate a new walker object and check brushes
+ walker = VisportalChecker()
+ GlobalSceneGraph.root().traverse(walker)
+
+ # Notify the user about the results
+ msg = '%d visportals checked, %d have errors' % (results.numVisportals, len(results.invalidPortals)) + '\n\n'
+
+ if results.numVisportals == 0:
+ msg = 'There are no visportals in this map.'
+
+ if len(results.invalidPortals) > 0:
+ # Unselect everything in the scene before highlighting the problematic portals
+ GlobalSelectionSystem.setSelectedAll(0)
+
+ # Highlight the brushes one by one
+ for brush in results.invalidPortals:
+ brush.setSelected(1)
+
+ msg += 'The problematic visportals have been highlighted.'
+
+ GlobalDialogManager.createMessageBox('Visportal Test Results', msg, Dialog.CONFIRM).run()
+
+if __executeCommand__:
+ execute()
diff --git a/install/ui/findandreplacedialog.fbp b/install/ui/findandreplacedialog.fbp
index 0ce16e1..811de25 100644
--- a/install/ui/findandreplacedialog.fbp
+++ b/install/ui/findandreplacedialog.fbp
@@ -920,7 +920,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">6</property>
- <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxRIGHT</property>
+ <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
<property name="proportion">1</property>
<object class="wxStaticText" expanded="1">
<property name="BottomDockable">1</property>
@@ -1003,7 +1003,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">0</property>
- <property name="flag">wxALIGN_RIGHT|wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</property>
+ <property name="flag">wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
diff --git a/install/ui/findandreplacedialog.xrc b/install/ui/findandreplacedialog.xrc
index 3e547a7..4ee8ad3 100644
--- a/install/ui/findandreplacedialog.xrc
+++ b/install/ui/findandreplacedialog.xrc
@@ -1,150 +1,150 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
- <object class="wxPanel" name="FindReplaceDialogMainPanel">
- <style>wxTAB_TRAVERSAL</style>
- <size>500,200</size>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>12</border>
- <object class="wxFlexGridSizer">
- <rows>2</rows>
- <cols>4</cols>
- <vgap>3</vgap>
- <hgap>0</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxStaticText" name="m_staticText1">
- <label>Find:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxTextCtrl" name="FindReplaceDialogFindEntry">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxBitmapButton" name="FindReplaceDialogFindSelectButton">
- <style>wxBU_AUTODRAW</style>
- <bitmap stock_id="darkradiant:folder16.png" stock_client="">undefined.png</bitmap>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>5</border>
- <object class="wxBitmapButton" name="FindReplaceDialogFindPickButton">
- <style>wxBU_AUTODRAW</style>
- <bitmap stock_id="darkradiant:texture_pick.png" stock_client="">undefined.png</bitmap>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxStaticText" name="m_staticText3">
- <label>Replace:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxTextCtrl" name="FindReplaceDialogReplaceEntry">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxBitmapButton" name="FindReplaceDialogReplaceSelectButton">
- <style>wxBU_AUTODRAW</style>
- <bitmap stock_id="darkradiant:folder16.png" stock_client="">undefined.png</bitmap>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>5</border>
- <object class="wxBitmapButton" name="FindReplaceDialogReplacePickButton">
- <style>wxBU_AUTODRAW</style>
- <bitmap stock_id="darkradiant:texture_pick.png" stock_client="">undefined.png</bitmap>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxLEFT</flag>
- <border>12</border>
- <object class="wxCheckBox" name="FindReplaceDialogSearchCurSelection">
- <label>Search current selection only</label>
- <checked>0</checked>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>12</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="FindReplaceDialogStatusLabel">
- <size>200,-1</size>
- <label>x shader(s) replaced.</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_RIGHT|wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxLEFT</flag>
- <border>6</border>
- <object class="wxButton" name="FindReplaceDialogFindButton">
- <label>Find and Replace</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxLEFT</flag>
- <border>6</border>
- <object class="wxButton" name="FindReplaceDialogCloseButton">
- <label>Close</label>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
+ <object class="wxPanel" name="FindReplaceDialogMainPanel">
+ <style>wxTAB_TRAVERSAL</style>
+ <size>500,200</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>12</border>
+ <object class="wxFlexGridSizer">
+ <rows>2</rows>
+ <cols>4</cols>
+ <vgap>3</vgap>
+ <hgap>0</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxStaticText" name="m_staticText1">
+ <label>Find:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxTextCtrl" name="FindReplaceDialogFindEntry">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxBitmapButton" name="FindReplaceDialogFindSelectButton">
+ <style>wxBU_AUTODRAW</style>
+ <bitmap stock_id="darkradiant:folder16.png" stock_client="">undefined.png</bitmap>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>5</border>
+ <object class="wxBitmapButton" name="FindReplaceDialogFindPickButton">
+ <style>wxBU_AUTODRAW</style>
+ <bitmap stock_id="darkradiant:texture_pick.png" stock_client="">undefined.png</bitmap>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxStaticText" name="m_staticText3">
+ <label>Replace:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxTextCtrl" name="FindReplaceDialogReplaceEntry">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxBitmapButton" name="FindReplaceDialogReplaceSelectButton">
+ <style>wxBU_AUTODRAW</style>
+ <bitmap stock_id="darkradiant:folder16.png" stock_client="">undefined.png</bitmap>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>5</border>
+ <object class="wxBitmapButton" name="FindReplaceDialogReplacePickButton">
+ <style>wxBU_AUTODRAW</style>
+ <bitmap stock_id="darkradiant:texture_pick.png" stock_client="">undefined.png</bitmap>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT</flag>
+ <border>12</border>
+ <object class="wxCheckBox" name="FindReplaceDialogSearchCurSelection">
+ <label>Search current selection only</label>
+ <checked>0</checked>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>12</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="FindReplaceDialogStatusLabel">
+ <size>200,-1</size>
+ <label>x shader(s) replaced.</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxBOTTOM|wxLEFT|wxRIGHT|wxTOP</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT</flag>
+ <border>6</border>
+ <object class="wxButton" name="FindReplaceDialogFindButton">
+ <label>Find and Replace</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT</flag>
+ <border>6</border>
+ <object class="wxButton" name="FindReplaceDialogCloseButton">
+ <label>Close</label>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
</resource>
diff --git a/install/ui/particleeditor.fbp b/install/ui/particleeditor.fbp
index 8aa1ed0..21f34e2 100644
--- a/install/ui/particleeditor.fbp
+++ b/install/ui/particleeditor.fbp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
- <FileVersion major="1" minor="11" />
+ <FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
@@ -1704,6 +1704,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -2775,6 +2776,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3064,6 +3066,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3353,6 +3356,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3725,6 +3729,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3895,6 +3900,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -4263,6 +4269,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -4552,6 +4559,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -4841,6 +4849,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -5130,6 +5139,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -5419,6 +5429,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -5708,6 +5719,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -6184,6 +6196,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -6462,6 +6475,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -6834,6 +6848,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -7112,6 +7127,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -7484,6 +7500,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -7762,6 +7779,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -8134,6 +8152,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -8412,6 +8431,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -8701,6 +8721,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -9078,6 +9099,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -9721,6 +9743,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -10010,6 +10033,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -10299,6 +10323,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -10588,6 +10613,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -11596,6 +11622,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -11885,6 +11912,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -12708,6 +12736,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -12997,6 +13026,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -13286,6 +13316,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -14037,6 +14068,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -14326,6 +14358,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -14615,6 +14648,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -14904,6 +14938,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -15193,6 +15228,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -15482,6 +15518,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -15784,7 +15821,7 @@
</object>
<object class="sizeritem" expanded="1">
<property name="border">6</property>
- <property name="flag">wxALIGN_RIGHT|wxLEFT</property>
+ <property name="flag">wxLEFT</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
diff --git a/install/ui/particleeditor.xrc b/install/ui/particleeditor.xrc
index 0d21131..b9b8b21 100644
--- a/install/ui/particleeditor.xrc
+++ b/install/ui/particleeditor.xrc
@@ -1,2146 +1,2146 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
- <object class="wxPanel" name="ParticleEditorMainPanel">
- <style>wxTAB_TRAVERSAL</style>
- <size>800,665</size>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>12</border>
- <object class="wxSplitterWindow" name="ParticleEditorSplitter">
- <style>wxSP_3D</style>
- <sashpos>0</sashpos>
- <gravity>0</gravity>
- <minsize>0</minsize>
- <orientation>vertical</orientation>
- <object class="wxPanel" name="m_panel1">
- <style>wxTAB_TRAVERSAL</style>
- <size>250,-1</size>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxBOTTOM</flag>
- <border>6</border>
- <object class="wxStaticText" name="ParticleEditorDefinitionLabel">
- <label>Particle Definitions</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>3</option>
- <flag>wxEXPAND|wxLEFT</flag>
- <border>12</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND | wxALL</flag>
- <border>5</border>
- <object class="wxPanel" name="ParticleEditorDefinitionView">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxEXPAND|wxLEFT</flag>
- <border>6</border>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>0</border>
- <object class="wxButton" name="ParticleEditorNewDefButton">
- <label>New</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorSaveDefButton">
- <label>Save</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorCopyDefButton">
- <label>Copy</label>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxBOTTOM|wxTOP</flag>
- <border>6</border>
- <object class="wxStaticText" name="ParticleEditorStageLabel">
- <label>Particle Stages</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>2</option>
- <flag>wxEXPAND | wxALL</flag>
- <border>0</border>
- <object class="wxPanel" name="ParticleEditorStagePanel">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND|wxLEFT</flag>
- <border>12</border>
- <object class="wxPanel" name="ParticleEditorStageView">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxEXPAND|wxLEFT</flag>
- <border>6</border>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxBOTTOM|wxEXPAND</flag>
- <border>6</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxRIGHT</flag>
- <border>6</border>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>0</border>
- <object class="wxButton" name="ParticleEditorAddStageButton">
- <label>Add</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP|wxEXPAND</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorRemoveStageButton">
- <label>Remove</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP|wxEXPAND</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorToggleStageButton">
- <label>Toggle Visibility</label>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag></flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>0</border>
- <object class="wxButton" name="ParticleEditorMoveUpStageButton">
- <label>Up</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP|wxEXPAND</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorMoveDownStageButton">
- <label>Down</label>
- <default>0</default>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxTOP|wxEXPAND</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorDuplicateStageButton">
- <label>Duplicate</label>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_RIGHT</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText4">
- <label>Depth Hack:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>0</border>
- <object class="wxSpinCtrl" name="ParticleEditorDepthHack">
- <style>wxSP_ARROW_KEYS</style>
- <size>80,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxBOTTOM</flag>
- <border>12</border>
- <object class="wxStaticText" name="ParticleEditorStageSettingsLabel">
- <label>Stage Settings</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxEXPAND|wxLEFT</flag>
- <border>12</border>
- <object class="wxNotebook" name="ParticleEditorSettingsNotebook">
- <object class="notebookpage">
- <label>Shader</label>
- <selected>0</selected>
- <object class="wxPanel" name="m_panel5">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText8">
- <label>Shader:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxTextCtrl" name="ParticleEditorStageShader">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText9">
- <label>Colour:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxTextCtrl" name="ParticleEditorStageColour">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText10">
- <label>Fade Colour:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxTextCtrl" name="ParticleEditorStageFadeColour">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxCheckBox" name="ParticleEditorStageUseEntityColour">
- <label>Use Entity Colour</label>
- <checked>0</checked>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText11">
- <label>Fade In Fraction:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageFadeInFrac">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageFadeInFracSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText12">
- <label>Fade Out Fraction:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageFadeOutFrac">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageFadeOutFracSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText13">
- <label>Fade Index Fraction:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageFadeIdxFrac">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageFadeIdxFracSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText14">
- <label>Animation:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText15">
- <label>Frames:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAnimFrames">
- <style>wxSP_ARROW_KEYS</style>
- <size>60,-1</size>
- <value>0</value>
- <min>0</min>
- <max>9999</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxLEFT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText16">
- <label>Rate:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>0</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAnimRate">
- <style>wxSP_ARROW_KEYS</style>
- <size>60,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxLEFT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText17">
- <label>FPS</label>
- <wrap>-1</wrap>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="notebookpage">
- <label>Count / Time</label>
- <selected>1</selected>
- <object class="wxPanel" name="m_panel6">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText111">
- <label>Count:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageCount">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>999</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageCountSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>0</value>
- <min>0</min>
- <max>999</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText121">
- <label>Duration / sec:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageDuration">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageDurationSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText131">
- <label>Bunching:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageBunching">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageBunchingSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1311">
- <label>Cycles:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageCycles">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>999</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageCyclesSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>1</value>
- <min>1</min>
- <max>999</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText13111">
- <label>Time Offset / sec:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageTimeOffset">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageTimeOffsetSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText131111">
- <label>Dead Time / sec:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageDeadTime">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageDeadTimeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="notebookpage">
- <label>Size / Speed</label>
- <selected>0</selected>
- <object class="wxPanel" name="m_panel7">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1111">
- <label>Speed:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText66">
- <label>From:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageSpeedFrom">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageSpeedFromSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText67">
- <label>To:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageSpeedTo">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageSpeedToSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1211">
- <label>Size:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText661">
- <label>From:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageSizeFrom">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageSizeFromSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText671">
- <label>To:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageSizeTo">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageSizeToSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1312">
- <label>Rotation Speed:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText6611">
- <label>From:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageRotationSpeedFrom">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageRotationSpeedFromSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText6711">
- <label>To:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageRotationSpeedTo">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageRotationSpeedToSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText13112">
- <label>Aspect Ratio:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText6612">
- <label>From:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAspectFrom">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageAspectFromSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
- <border>6</border>
- <object class="wxStaticText" name="m_staticText6712">
- <label>To:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAspectTo">
- <style>wxSP_ARROW_KEYS</style>
- <size>50,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>0</border>
- <object class="wxSlider" name="ParticleEditorStageAspectToSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText131112">
- <label>Gravity:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageGravity">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageGravitySlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxLEFT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxCheckBox" name="ParticleEditorStageUseWorldGravity">
- <label>Use World Gravity</label>
- <checked>0</checked>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1311111">
- <label>Bounds Expansion:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageBoundsExpansion">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="notebookpage">
- <label>Distribution</label>
- <selected>0</selected>
- <object class="wxPanel" name="m_panel61">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1112">
- <label>Shape:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageShapeRect">
- <style>wxRB_GROUP</style>
- <label>Rectangular</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageShapeCyl">
- <label>Cylindric</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageSpherical">
- <label>Spherical</label>
- <value>0</value>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1212">
- <label>X Size:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageXSize">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageXSizeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1313">
- <label>Y Size:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageYSize">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageYSizeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText13113">
- <label>Z Size:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageZSize">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageZSizeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageRingSizeLabel">
- <label>Ring Size:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageRingSize">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageRingSizeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText1311112">
- <label>Offset:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxTextCtrl" name="ParticleEditorStageOffset">
- <value></value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText97">
- <label>Randomness:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</flag>
- <border>3</border>
- <object class="wxCheckBox" name="ParticleEditorStageRandomDist">
- <label>Distribute Particles randomly within Volume</label>
- <checked>0</checked>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="notebookpage">
- <label>Direction / Orientation</label>
- <selected>0</selected>
- <object class="wxPanel" name="m_panel611">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText11121">
- <label>Direction:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageCone">
- <style>wxRB_GROUP</style>
- <label>Cone</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOutward">
- <label>Outward</label>
- <value>0</value>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageConeAngleLabel">
- <label>Cone Angle:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageConeAngle">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageConeAngleSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageUpwardBiasLabel">
- <label>Upward Bias:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageUpwardBias">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageUpwardBiasSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText131131">
- <label>Orientation:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxBOTTOM|wxRIGHT|wxTOP|wxALIGN_CENTER_VERTICAL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOrientView">
- <style>wxRB_GROUP</style>
- <label>View</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOrientAimed">
- <label>Aimed</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOrientX">
- <label>X</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOrientY">
- <label>Y</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStageOrientZ">
- <label>Z</label>
- <value>0</value>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageTrailsLabel">
- <label>Trails:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageTrails">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>500</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageTrailsSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageTimeLabel">
- <label>Time:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAimedTime">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageAimedTimeSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText971">
- <label>Initial Angle:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageInitialAngle">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageInitialAngleSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="notebookpage">
- <label>Path</label>
- <selected>0</selected>
- <object class="wxPanel" name="m_panel6111">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALL|wxEXPAND</flag>
- <border>6</border>
- <object class="wxFlexGridSizer">
- <rows>7</rows>
- <cols>2</cols>
- <vgap>6</vgap>
- <hgap>12</hgap>
- <growablecols>1</growablecols>
- <growablerows></growablerows>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="m_staticText111211">
- <label>Path Type:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStagePathStandard">
- <style>wxRB_GROUP</style>
- <label>Standard</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStagePathFlies">
- <label>Flies</label>
- <value>0</value>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALL</flag>
- <border>3</border>
- <object class="wxRadioButton" name="ParticleEditorStagePathHelix">
- <label>Helix</label>
- <value>0</value>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageRadialSpeedLabel">
- <label>Radial Speed:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageRadialSpeed">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageRadialSpeedSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageAxialSpeedLabel">
- <label>Axial Speed:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageAxialSpeed">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageAxialSpeedSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageSphereRadiusLabel">
- <label>Sphere Radius:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageSphereRadius">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageSphereRadiusSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageCylSizeXLabel">
- <label>Cylinder Size X:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>5</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeX">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageCylSizeXSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageCylSizeYLabel">
- <label>Cylinder Size Y:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeY">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageCylSizeYSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorStageCylSizeZLabel">
- <label>Cylinder Size Z:</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxEXPAND</flag>
- <border>0</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
- <border>6</border>
- <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeZ">
- <style>wxSP_ARROW_KEYS</style>
- <size>70,-1</size>
- <value>0</value>
- <min>0</min>
- <max>10</max>
- </object>
- </object>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxSlider" name="ParticleEditorStageCylSizeZSlider">
- <style>wxSL_HORIZONTAL</style>
- <value>50</value>
- <min>0</min>
- <max>100</max>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
- <object class="wxPanel" name="ParticleEditorPreviewPanel">
- <style>wxTAB_TRAVERSAL</style>
- <object class="wxBoxSizer">
- <orient>wxVERTICAL</orient>
- </object>
- </object>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</flag>
- <border>12</border>
- <object class="wxBoxSizer">
- <orient>wxHORIZONTAL</orient>
- <object class="sizeritem">
- <option>1</option>
- <flag>wxALIGN_CENTER_VERTICAL</flag>
- <border>5</border>
- <object class="wxStaticText" name="ParticleEditorSaveNote">
- <label>Note: changes will be written to the file .....</label>
- <wrap>-1</wrap>
- </object>
- </object>
- <object class="sizeritem">
- <option>0</option>
- <flag>wxALIGN_RIGHT|wxLEFT</flag>
- <border>6</border>
- <object class="wxButton" name="ParticleEditorCloseButton">
- <label>Close</label>
- <default>0</default>
- </object>
- </object>
- </object>
- </object>
- </object>
- </object>
+ <object class="wxPanel" name="ParticleEditorMainPanel">
+ <style>wxTAB_TRAVERSAL</style>
+ <size>800,665</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>12</border>
+ <object class="wxSplitterWindow" name="ParticleEditorSplitter">
+ <style>wxSP_3D</style>
+ <sashpos>0</sashpos>
+ <gravity>0</gravity>
+ <minsize>0</minsize>
+ <orientation>vertical</orientation>
+ <object class="wxPanel" name="m_panel1">
+ <style>wxTAB_TRAVERSAL</style>
+ <size>250,-1</size>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxBOTTOM</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="ParticleEditorDefinitionLabel">
+ <label>Particle Definitions</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>3</option>
+ <flag>wxEXPAND|wxLEFT</flag>
+ <border>12</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND | wxALL</flag>
+ <border>5</border>
+ <object class="wxPanel" name="ParticleEditorDefinitionView">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxEXPAND|wxLEFT</flag>
+ <border>6</border>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>0</border>
+ <object class="wxButton" name="ParticleEditorNewDefButton">
+ <label>New</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorSaveDefButton">
+ <label>Save</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorCopyDefButton">
+ <label>Copy</label>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxBOTTOM|wxTOP</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="ParticleEditorStageLabel">
+ <label>Particle Stages</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>2</option>
+ <flag>wxEXPAND | wxALL</flag>
+ <border>0</border>
+ <object class="wxPanel" name="ParticleEditorStagePanel">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND|wxLEFT</flag>
+ <border>12</border>
+ <object class="wxPanel" name="ParticleEditorStageView">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxEXPAND|wxLEFT</flag>
+ <border>6</border>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxBOTTOM|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxButton" name="ParticleEditorAddStageButton">
+ <label>Add</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorRemoveStageButton">
+ <label>Remove</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorToggleStageButton">
+ <label>Toggle Visibility</label>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag></flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxButton" name="ParticleEditorMoveUpStageButton">
+ <label>Up</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorMoveDownStageButton">
+ <label>Down</label>
+ <default>0</default>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxTOP|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorDuplicateStageButton">
+ <label>Duplicate</label>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_RIGHT</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText4">
+ <label>Depth Hack:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>0</border>
+ <object class="wxSpinCtrl" name="ParticleEditorDepthHack">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>80,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxBOTTOM</flag>
+ <border>12</border>
+ <object class="wxStaticText" name="ParticleEditorStageSettingsLabel">
+ <label>Stage Settings</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxEXPAND|wxLEFT</flag>
+ <border>12</border>
+ <object class="wxNotebook" name="ParticleEditorSettingsNotebook">
+ <object class="notebookpage">
+ <label>Shader</label>
+ <selected>0</selected>
+ <object class="wxPanel" name="m_panel5">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText8">
+ <label>Shader:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxTextCtrl" name="ParticleEditorStageShader">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText9">
+ <label>Colour:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxTextCtrl" name="ParticleEditorStageColour">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText10">
+ <label>Fade Colour:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxTextCtrl" name="ParticleEditorStageFadeColour">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxCheckBox" name="ParticleEditorStageUseEntityColour">
+ <label>Use Entity Colour</label>
+ <checked>0</checked>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText11">
+ <label>Fade In Fraction:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageFadeInFrac">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageFadeInFracSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText12">
+ <label>Fade Out Fraction:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageFadeOutFrac">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageFadeOutFracSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText13">
+ <label>Fade Index Fraction:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageFadeIdxFrac">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageFadeIdxFracSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText14">
+ <label>Animation:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText15">
+ <label>Frames:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAnimFrames">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>60,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>9999</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText16">
+ <label>Rate:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>0</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAnimRate">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>60,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxLEFT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText17">
+ <label>FPS</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="notebookpage">
+ <label>Count / Time</label>
+ <selected>1</selected>
+ <object class="wxPanel" name="m_panel6">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText111">
+ <label>Count:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageCount">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>999</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageCountSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>0</value>
+ <min>0</min>
+ <max>999</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText121">
+ <label>Duration / sec:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageDuration">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageDurationSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText131">
+ <label>Bunching:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageBunching">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageBunchingSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1311">
+ <label>Cycles:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageCycles">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>999</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageCyclesSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>1</value>
+ <min>1</min>
+ <max>999</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText13111">
+ <label>Time Offset / sec:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageTimeOffset">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageTimeOffsetSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText131111">
+ <label>Dead Time / sec:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageDeadTime">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageDeadTimeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="notebookpage">
+ <label>Size / Speed</label>
+ <selected>0</selected>
+ <object class="wxPanel" name="m_panel7">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1111">
+ <label>Speed:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText66">
+ <label>From:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageSpeedFrom">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageSpeedFromSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText67">
+ <label>To:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageSpeedTo">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageSpeedToSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1211">
+ <label>Size:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText661">
+ <label>From:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageSizeFrom">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageSizeFromSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText671">
+ <label>To:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageSizeTo">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageSizeToSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1312">
+ <label>Rotation Speed:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText6611">
+ <label>From:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageRotationSpeedFrom">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageRotationSpeedFromSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText6711">
+ <label>To:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageRotationSpeedTo">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageRotationSpeedToSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText13112">
+ <label>Aspect Ratio:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText6612">
+ <label>From:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAspectFrom">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageAspectFromSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
+ <border>6</border>
+ <object class="wxStaticText" name="m_staticText6712">
+ <label>To:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAspectTo">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>50,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>0</border>
+ <object class="wxSlider" name="ParticleEditorStageAspectToSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText131112">
+ <label>Gravity:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageGravity">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageGravitySlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxCheckBox" name="ParticleEditorStageUseWorldGravity">
+ <label>Use World Gravity</label>
+ <checked>0</checked>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1311111">
+ <label>Bounds Expansion:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageBoundsExpansion">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="notebookpage">
+ <label>Distribution</label>
+ <selected>0</selected>
+ <object class="wxPanel" name="m_panel61">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1112">
+ <label>Shape:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageShapeRect">
+ <style>wxRB_GROUP</style>
+ <label>Rectangular</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageShapeCyl">
+ <label>Cylindric</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageSpherical">
+ <label>Spherical</label>
+ <value>0</value>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1212">
+ <label>X Size:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageXSize">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageXSizeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1313">
+ <label>Y Size:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageYSize">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageYSizeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText13113">
+ <label>Z Size:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageZSize">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageZSizeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageRingSizeLabel">
+ <label>Ring Size:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageRingSize">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageRingSizeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText1311112">
+ <label>Offset:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxTextCtrl" name="ParticleEditorStageOffset">
+ <value></value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText97">
+ <label>Randomness:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM</flag>
+ <border>3</border>
+ <object class="wxCheckBox" name="ParticleEditorStageRandomDist">
+ <label>Distribute Particles randomly within Volume</label>
+ <checked>0</checked>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="notebookpage">
+ <label>Direction / Orientation</label>
+ <selected>0</selected>
+ <object class="wxPanel" name="m_panel611">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText11121">
+ <label>Direction:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageCone">
+ <style>wxRB_GROUP</style>
+ <label>Cone</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOutward">
+ <label>Outward</label>
+ <value>0</value>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageConeAngleLabel">
+ <label>Cone Angle:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageConeAngle">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageConeAngleSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageUpwardBiasLabel">
+ <label>Upward Bias:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageUpwardBias">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageUpwardBiasSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText131131">
+ <label>Orientation:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxBOTTOM|wxRIGHT|wxTOP|wxALIGN_CENTER_VERTICAL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOrientView">
+ <style>wxRB_GROUP</style>
+ <label>View</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOrientAimed">
+ <label>Aimed</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOrientX">
+ <label>X</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOrientY">
+ <label>Y</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStageOrientZ">
+ <label>Z</label>
+ <value>0</value>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageTrailsLabel">
+ <label>Trails:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageTrails">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>500</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageTrailsSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageTimeLabel">
+ <label>Time:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAimedTime">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageAimedTimeSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText971">
+ <label>Initial Angle:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageInitialAngle">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageInitialAngleSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="notebookpage">
+ <label>Path</label>
+ <selected>0</selected>
+ <object class="wxPanel" name="m_panel6111">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALL|wxEXPAND</flag>
+ <border>6</border>
+ <object class="wxFlexGridSizer">
+ <rows>7</rows>
+ <cols>2</cols>
+ <vgap>6</vgap>
+ <hgap>12</hgap>
+ <growablecols>1</growablecols>
+ <growablerows></growablerows>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="m_staticText111211">
+ <label>Path Type:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStagePathStandard">
+ <style>wxRB_GROUP</style>
+ <label>Standard</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStagePathFlies">
+ <label>Flies</label>
+ <value>0</value>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALL</flag>
+ <border>3</border>
+ <object class="wxRadioButton" name="ParticleEditorStagePathHelix">
+ <label>Helix</label>
+ <value>0</value>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageRadialSpeedLabel">
+ <label>Radial Speed:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageRadialSpeed">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageRadialSpeedSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageAxialSpeedLabel">
+ <label>Axial Speed:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageAxialSpeed">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageAxialSpeedSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageSphereRadiusLabel">
+ <label>Sphere Radius:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageSphereRadius">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageSphereRadiusSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageCylSizeXLabel">
+ <label>Cylinder Size X:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>5</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeX">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageCylSizeXSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageCylSizeYLabel">
+ <label>Cylinder Size Y:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeY">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageCylSizeYSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorStageCylSizeZLabel">
+ <label>Cylinder Size Z:</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxEXPAND</flag>
+ <border>0</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <border>6</border>
+ <object class="wxSpinCtrl" name="ParticleEditorStageCylSizeZ">
+ <style>wxSP_ARROW_KEYS</style>
+ <size>70,-1</size>
+ <value>0</value>
+ <min>0</min>
+ <max>10</max>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxSlider" name="ParticleEditorStageCylSizeZSlider">
+ <style>wxSL_HORIZONTAL</style>
+ <value>50</value>
+ <min>0</min>
+ <max>100</max>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="wxPanel" name="ParticleEditorPreviewPanel">
+ <style>wxTAB_TRAVERSAL</style>
+ <object class="wxBoxSizer">
+ <orient>wxVERTICAL</orient>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</flag>
+ <border>12</border>
+ <object class="wxBoxSizer">
+ <orient>wxHORIZONTAL</orient>
+ <object class="sizeritem">
+ <option>1</option>
+ <flag>wxALIGN_CENTER_VERTICAL</flag>
+ <border>5</border>
+ <object class="wxStaticText" name="ParticleEditorSaveNote">
+ <label>Note: changes will be written to the file .....</label>
+ <wrap>-1</wrap>
+ </object>
+ </object>
+ <object class="sizeritem">
+ <option>0</option>
+ <flag>wxLEFT</flag>
+ <border>6</border>
+ <object class="wxButton" name="ParticleEditorCloseButton">
+ <label>Close</label>
+ <default>0</default>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
+ </object>
</resource>
diff --git a/install/ui/stimeditor.fbp b/install/ui/stimeditor.fbp
index 68801f7..679a0db 100644
--- a/install/ui/stimeditor.fbp
+++ b/install/ui/stimeditor.fbp
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
- <FileVersion major="1" minor="11" />
+ <FileVersion major="1" minor="13" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
@@ -627,6 +627,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -797,6 +798,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -885,7 +887,7 @@
</object>
<object class="sizeritem" expanded="0">
<property name="border">6</property>
- <property name="flag">wxALIGN_RIGHT|wxRIGHT|wxALIGN_CENTER_VERTICAL</property>
+ <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxSpinCtrl" expanded="0">
<property name="BottomDockable">1</property>
@@ -967,6 +969,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -1137,6 +1140,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -1569,6 +1573,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -1945,6 +1950,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -2132,7 +2138,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
- <property name="flag">wxEXPAND|wxALIGN_CENTER_VERTICAL</property>
+ <property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxSpinCtrl" expanded="1">
<property name="BottomDockable">1</property>
@@ -2214,6 +2220,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -2483,6 +2490,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -2748,6 +2756,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3006,6 +3015,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
@@ -3272,6 +3282,7 @@
<event name="OnSize"></event>
<event name="OnSpinCtrl"></event>
<event name="OnSpinCtrlText"></event>
+ <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
diff --git a/install/ui/stimeditor.xrc b/install/ui/stimeditor.xrc
index 75a742f..f37bb25 100644
--- a/install/ui/stimeditor.xrc
+++ b/install/ui/stimeditor.xrc
@@ -112,7 +112,7 @@
</object>
<object class="sizeritem">
<option>0</option>
- <flag>wxALIGN_RIGHT|wxRIGHT|wxALIGN_CENTER_VERTICAL</flag>
+ <flag>wxALIGN_CENTER_VERTICAL|wxRIGHT</flag>
<border>6</border>
<object class="wxSpinCtrl" name="StimEditorAcivationTimerSecond">
<style>wxSP_ARROW_KEYS</style>
@@ -281,7 +281,7 @@
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<option>1</option>
- <flag>wxEXPAND|wxALIGN_CENTER_VERTICAL</flag>
+ <flag>wxEXPAND</flag>
<border>5</border>
<object class="wxSpinCtrl" name="StimEditorDurationValue">
<style>wxSP_ARROW_KEYS</style>
diff --git a/install/user.xml b/install/user.xml
index 04f7423..6c4e6ea 100644
--- a/install/user.xml
+++ b/install/user.xml
@@ -8,273 +8,283 @@
<fs_game value="darkmod" />
</game>
<ui>
- <commandsystem>
- <binds>
- <bind name="SelectNudgeLeft" value="NudgeSelected left" readonly="1" />
- <bind name="SelectNudgeRight" value="NudgeSelected right" readonly="1" />
- <bind name="SelectNudgeUp" value="NudgeSelected up" readonly="1" />
- <bind name="SelectNudgeDown" value="NudgeSelected down" readonly="1" />
- </binds>
- </commandsystem>
- <map>
- <numMRU value="5" />
- <loadLastMap value="0" />
- <autoSaveEnabled value="1" />
- <autoSaveInterval value="5" />
- <autoSaveSnapshots value="0" />
- <snapshotFolder value="snapshots/" />
- <maxSnapshotFolderSize value="100" />
- <loadStatusInterleave value="50" />
- <saveStatusInterleave value="50" />
- </map>
- <undo>
- <queueSize value="256" />
- </undo>
- <stimResponseEditor>
- <window xPosition="80" yPosition="100" width="740" height="480" />
- <showStimTypeIDs value="0" />
- </stimResponseEditor>
- <lightInspector>
- <window xPosition="100" yPosition="150" width="780" height="400" />
- <instantApply value="1" />
- </lightInspector>
- <ModelSelector>
- <!-- Size of the model preview, as a fraction of the screen height. The
- preview is always square.
- -->
- <previewSizeFactor value="0.7"/>
+ <commandsystem>
+ <binds>
+ <bind name="SelectNudgeLeft" value="NudgeSelected left" readonly="1" />
+ <bind name="SelectNudgeRight" value="NudgeSelected right" readonly="1" />
+ <bind name="SelectNudgeUp" value="NudgeSelected up" readonly="1" />
+ <bind name="SelectNudgeDown" value="NudgeSelected down" readonly="1" />
+ </binds>
+ </commandsystem>
+ <map>
+ <numMRU value="5" />
+ <loadLastMap value="0" />
+ <autoSaveEnabled value="1" />
+ <autoSaveInterval value="5" />
+ <autoSaveSnapshots value="0" />
+ <snapshotFolder value="snapshots/" />
+ <maxSnapshotFolderSize value="100" />
+ <loadStatusInterleave value="50" />
+ <saveStatusInterleave value="50" />
+ </map>
+ <undo>
+ <queueSize value="256" />
+ </undo>
+ <stimResponseEditor>
+ <window xPosition="80" yPosition="100" width="900" height="560" />
+ <showStimTypeIDs value="0" />
+ </stimResponseEditor>
+ <lightInspector>
+ <window xPosition="100" yPosition="150" width="780" height="400" />
+ <instantApply value="1" />
+ </lightInspector>
+ <ModelSelector>
+ <!-- Size of the model preview, as a fraction of the screen height. The
+ preview is always square.
+ -->
+ <previewSizeFactor value="0.7"/>
</ModelSelector>
- <showAllLightRadii value="0"/>
- <alwaysShowLightVertices value="1"/>
+ <prefabSelector>
+ <insertAsGroup value="1"/>
+ </prefabSelector>
+ <aasViewer>
+ <showNumbers value="1" />
+ <hideDistantAreas value="0" />
+ <hideDistance value="800" />
+ </aasViewer>
+ <showAllLightRadii value="0"/>
+ <alwaysShowLightVertices value="1"/>
<rotateObjectsIndependently value="0" />
- <rotationPivotIsOrigin value="0" />
- <selectionEpsilon value="8.0" />
- <dragResizeEntitiesSymmetrically value="1" />
- <transientComponentSelection value="1" />
- <offsetClonedObjects value="1" />
- <transformDialog>
- <window xPosition="150" yPosition="200" width="260" height="314" />
- <rotXStep value="45" />
- <rotYStep value="45" />
- <rotZStep value="45" />
- <scaleXStep value="1.1" />
- <scaleYStep value="1.1" />
- <scaleZStep value="1.1" />
- </transformDialog>
- <layers>
- <controlDialog>
- <window xPosition="57" yPosition="449" width="164" height="299" />
- </controlDialog>
- </layers>
- <textures>
- <shaderChooser>
- <window xPosition="200" yPosition="100" width="550" height="500" />
- </shaderChooser>
- <browser>
- <hideUnused value="0" />
- <textureScale value="2" />
- <uniformSize value="128" />
- <showScrollBar value="1" />
- <mouseWheelIncrement value="64" />
- <showFilter value="0" />
- <contextMenuMouseEpsilon value="5" />
- <maxShadernameLength value="18" />
- <clampToUniformSize value="1" />
- </browser>
- <defaultTextureScale value="0.5" />
- <quality value="3" />
- <mode value="5" />
- <gamma value="1.0" />
- <surfaceInspector>
- <hShiftStep value="1" />
- <vShiftStep value="1" />
- <hScaleStep value="0.05" />
- <vScaleStep value="0.05" />
- <rotStep value="45" />
- <window xPosition="200" yPosition="100" width="370" height="440" />
- </surfaceInspector>
- <texTool>
- <gridActive value="1" />
- <faceVertexScalePivotIsCentroid value="0" />
- </texTool>
- </textures>
- <grid>
- <defaultGridPower value="3" />
- </grid>
- <mediaBrowser>
- <preLoadMediaTree value="1" />
- </mediaBrowser>
- <mainFrame>
- <windowLayout value="1" />
- <window xPosition="0" yPosition="0" width="800" height="580" state="4" />
- <regular>
- <pane name="vertical" position="650" />
- <pane name="horizontal" position="500" />
- <pane name="texcam" position="350" />
- </regular>
- <splitPane>
- <pane name="horizontal" position="300" />
- <pane name="vertical1" position="250" />
- <pane name="vertical2" position="250" />
- </splitPane>
- <floating>
- <groupDialogVisible value="1" />
- </floating>
- </mainFrame>
- <groupDialog>
- <window xPosition="50" yPosition="530" width="350" height="200" />
- </groupDialog>
- <entityList>
- <window xPosition="50" yPosition="530" width="250" height="400" />
- </entityList>
- <multiMonitor>
- <startMonitorNum value="0" />
- </multiMonitor>
- <xyview>
- <views name="default">
- <view type="XY" xPosition="500" yPosition="100" width="400" height="430"/>
- </views>
- <showGrid value="1" />
- <chaseMouse value="1" />
- <chaseMouseCap value="32" />
- <camXYUpdate value="0" />
- <solidSelectionBoxes value="0" />
- <showCrossHairs value="0" />
- <showEntityAngles value="1" />
- <showEntityNames value="0" />
- <showBlocks value="0" />
- <showSizeInfo value="1" />
- <defaultBlockSize value="1024" />
- <showCoordinates value="1" />
- <showOutline value="0" />
- <showAxes value="1" />
- <showWorkzone value="0" />
- <overlay>
- <visible value="0" />
- <transparency value="0.3" />
- <image value="" />
- <proportional value="1" />
- <translationX value="0.0" />
- <translationY value="0.0" />
- <scale value="1.0" />
- <scaleWithOrthoView value="1" />
- <panWithOrthoView value="0" />
- </overlay>
- <translateConstrained value="1" />
- <higherEntitySelectionPriority value="1" />
- </xyview>
- <clipper>
- <useCaulk value="1" />
- <caulkTexture value="textures/common/caulk" />
- </clipper>
- <brush>
- <textureLock value="1" />
- <emitCSGSubtractWarning value="1" />
- </brush>
- <patch>
- <subdivideThreshold value="2" />
- <patchInspector>
- <xCoordStep value="1.0" />
- <yCoordStep value="1.0" />
- <zCoordStep value="1.0" />
- <sCoordStep value="0.1" />
- <tCoordStep value="0.1" />
- <window xPosition="130" yPosition="100" width="280" height="480" />
- </patchInspector>
- </patch>
+ <rotationPivotIsOrigin value="0" />
+ <selectionEpsilon value="8.0" />
+ <dragResizeEntitiesSymmetrically value="1" />
+ <transientComponentSelection value="1" />
+ <offsetClonedObjects value="1" />
+ <transformDialog>
+ <window xPosition="150" yPosition="200" width="260" height="314" />
+ <rotXStep value="45" />
+ <rotYStep value="45" />
+ <rotZStep value="45" />
+ <scaleXStep value="1.1" />
+ <scaleYStep value="1.1" />
+ <scaleZStep value="1.1" />
+ </transformDialog>
+ <layers>
+ <controlDialog>
+ <window xPosition="57" yPosition="449" width="164" height="299" />
+ </controlDialog>
+ </layers>
+ <textures>
+ <shaderChooser>
+ <window xPosition="200" yPosition="100" width="550" height="500" />
+ </shaderChooser>
+ <browser>
+ <hideUnused value="0" />
+ <textureScale value="2" />
+ <uniformSize value="128" />
+ <showScrollBar value="1" />
+ <mouseWheelIncrement value="64" />
+ <showFilter value="0" />
+ <contextMenuMouseEpsilon value="5" />
+ <maxShadernameLength value="18" />
+ <clampToUniformSize value="1" />
+ </browser>
+ <defaultTextureScale value="0.5" />
+ <quality value="3" />
+ <mode value="5" />
+ <gamma value="1.0" />
+ <surfaceInspector>
+ <hShiftStep value="1" />
+ <vShiftStep value="1" />
+ <hScaleStep value="0.05" />
+ <vScaleStep value="0.05" />
+ <rotStep value="45" />
+ <window xPosition="200" yPosition="100" width="370" height="440" />
+ </surfaceInspector>
+ <texTool>
+ <gridActive value="1" />
+ <faceVertexScalePivotIsCentroid value="0" />
+ </texTool>
+ </textures>
+ <grid>
+ <defaultGridPower value="3" />
+ </grid>
+ <mediaBrowser>
+ <preLoadMediaTree value="1" />
+ </mediaBrowser>
+ <mainFrame>
+ <windowLayout value="1" />
+ <window xPosition="0" yPosition="0" width="800" height="580" state="4" />
+ <regular>
+ <pane name="vertical" position="650" />
+ <pane name="horizontal" position="500" />
+ <pane name="texcam" position="350" />
+ </regular>
+ <splitPane>
+ <pane name="horizontal" position="300" />
+ <pane name="vertical1" position="250" />
+ <pane name="vertical2" position="250" />
+ </splitPane>
+ <floating>
+ <groupDialogVisible value="1" />
+ </floating>
+ </mainFrame>
+ <groupDialog>
+ <window xPosition="50" yPosition="530" width="350" height="200" />
+ </groupDialog>
+ <entityList>
+ <window xPosition="50" yPosition="530" width="250" height="400" />
+ </entityList>
+ <multiMonitor>
+ <startMonitorNum value="0" />
+ </multiMonitor>
+ <xyview>
+ <views name="default">
+ <view type="XY" xPosition="500" yPosition="100" width="400" height="430"/>
+ </views>
+ <showGrid value="1" />
+ <chaseMouse value="1" />
+ <chaseMouseCap value="32" />
+ <camXYUpdate value="0" />
+ <solidSelectionBoxes value="0" />
+ <showCrossHairs value="0" />
+ <showEntityAngles value="1" />
+ <showEntityNames value="0" />
+ <showBlocks value="0" />
+ <showSizeInfo value="1" />
+ <defaultBlockSize value="1024" />
+ <showCoordinates value="1" />
+ <showOutline value="0" />
+ <showAxes value="1" />
+ <showWorkzone value="0" />
+ <overlay>
+ <visible value="0" />
+ <transparency value="0.3" />
+ <image value="" />
+ <proportional value="1" />
+ <translationX value="0.0" />
+ <translationY value="0.0" />
+ <scale value="1.0" />
+ <scaleWithOrthoView value="1" />
+ <panWithOrthoView value="0" />
+ </overlay>
+ <translateConstrained value="1" />
+ <higherEntitySelectionPriority value="1" />
+ </xyview>
+ <clipper>
+ <useCaulk value="1" />
+ <caulkTexture value="textures/common/caulk" />
+ </clipper>
+ <brush>
+ <textureLock value="1" />
+ <emitCSGSubtractWarning value="1" />
+ </brush>
+ <patch>
+ <patchInspector>
+ <xCoordStep value="1.0" />
+ <yCoordStep value="1.0" />
+ <zCoordStep value="1.0" />
+ <sCoordStep value="0.1" />
+ <tCoordStep value="0.1" />
+ <window xPosition="130" yPosition="100" width="280" height="480" />
+ </patchInspector>
+ </patch>
<particleEditor>
<window xPosition="0" yPosition="0" width="1000" height="830" />
<splitPos position="500" />
</particleEditor>
<camera>
- <toggleFreeMove value="1" />
- <enableCubicClipping value="1" />
- <discreteMovement value="1" />
- <invertMouseVerticalAxis value="0" />
- <movementSpeed value="100" />
- <rotationSpeed value="3" />
- <strafespeed value="0.65" />
- <!-- Use the forward strafe factor to invert the direction of the mouse movement -->
- <forwardStrafeFactor value="1" />
- <cubicScale value="13" />
- <drawMode value="2" />
- <window xPosition="37" yPosition="100" width="450" height="430" />
- </camera>
+ <toggleFreeMove value="1" />
+ <enableCubicClipping value="1" />
+ <discreteMovement value="1" />
+ <invertMouseVerticalAxis value="0" />
+ <movementSpeed value="100" />
+ <rotationSpeed value="3" />
+ <strafespeed value="0.65" />
+ <!-- Use the forward strafe factor to invert the direction of the mouse movement -->
+ <forwardStrafeFactor value="1" />
+ <cubicScale value="13" />
+ <drawMode value="2" />
+ <window xPosition="37" yPosition="100" width="450" height="430" />
+ </camera>
<toolbar name="view" align="horizontal">
- <toolbutton name="open" action="OpenMap" tooltip="Open a map file" icon="file_open.png"/>
- <toolbutton name="save" action="SaveMap" tooltip="Save the current map" icon="file_save.png"/>
- <separator/>
- <toolbutton name="changeviews" action="NextView" tooltip="Change views" icon="view_change.png"/>
- <toggletoolbutton name="cubicclip" action="ToggleCubicClip" tooltip="Cubic clip the camera view" icon="view_cubicclipping.png"/>
- <separator/>
- <toolbutton name="selectcompletetall" action="SelectCompleteTall" tooltip="Select complete tall" icon="selection_selectcompletetall.png" />
- <toolbutton name="selecttouching" action="SelectTouching" tooltip="Select touching" icon="selection_selecttouching.png"/>
- <toolbutton name="selectinside" action="SelectInside" tooltip="Select inside" icon="selection_selectinside.png"/>
- <separator/>
- <toggletoolbutton name="dragvertices" action="DragVertices" tooltip="Select Vertices" icon="modify_vertices.png"/>
- <toggletoolbutton name="dragedges" action="DragEdges" tooltip="Select Edges" icon="modify_edges.png"/>
- <toggletoolbutton name="dragfaces" action="DragFaces" tooltip="Select Faces" icon="modify_faces.png"/>
- <toggletoolbutton name="dragentities" action="DragEntities" tooltip="Select Entities" icon="select_entities.png"/>
- <toggletoolbutton name="selectionModeGroupPart" action="SelectionModeGroupPart" tooltip="Select Group Parts" icon="select_group_parts.png"/>
- <separator/>
- <toggletoolbutton name="showlightradii" action="ToggleShowAllLightRadii" tooltip="Show/hide all light volumes" icon="view_show_lightradii.png"/>
- <toggletoolbutton name="showspeakerradii" action="ToggleShowAllSpeakerRadii" tooltip="Show/hide all speaker volumes" icon="view_show_speakerradii.png"/>
- <separator/>
- <toggletoolbutton name="texturelock" action="TogTexLock" tooltip="Texture Lock" icon="texture_lock.png"/>
- <toggletoolbutton name="freeobjectrotation" action="ToggleFreeObjectRotation" tooltip="Rotate Objects independently" icon="free_model_rotation.png" />
- <toggletoolbutton name="togglerotationpivot" action="ToggleRotationPivot" tooltip="Rotate func_* Entities around origin" icon="rotation_pivot_origin.png" />
- <toggletoolbutton name="dragresizesymm" action="ToggleDragResizeEntitiesSymmetrically" tooltip="Drag-resize entities symmetrically (leave origin unchanged)" icon="dragresize_symm.png" />
- <toggletoolbutton name="offsetclones" action="ToggleOffsetClones" tooltip="Offset cloned objects by one grid unit to the right and downwards." icon="offset_clone.png" />
- <separator/>
- <toolbutton name="createDecals" action="CreateDecalsForFaces" tooltip="Create Decals for selected Faces" icon="create_decals.png"/>
- </toolbar>
- <toolbar name="edit" align="vertical">
- <toolbutton name="xflip" action="MirrorSelectionX" tooltip="x-axis Mirror" icon="brush_flipx.png"/>
- <toolbutton name="xrotate" action="RotateSelectionX" tooltip="x-axis Rotate" icon="brush_rotatex.png"/>
- <toolbutton name="yflip" action="MirrorSelectionY" tooltip="y-axis Mirror" icon="brush_flipy.png"/>
- <toolbutton name="yrotate" action="RotateSelectionY" tooltip="y-axis Rotate" icon="brush_rotatey.png"/>
- <toolbutton name="zflip" action="MirrorSelectionZ" tooltip="z-axis Mirror" icon="brush_flipz.png"/>
- <toolbutton name="zrotate" action="RotateSelectionZ" tooltip="z-axis Rotate" icon="brush_rotatez.png"/>
- <separator/>
- <toolbutton name="snaptogrid" action="SnapToGrid" tooltip="Snap selection to grid" icon="grid_snap.png"/>
+ <toolbutton name="open" action="OpenMap" tooltip="Open a map file" icon="file_open.png"/>
+ <toolbutton name="save" action="SaveMap" tooltip="Save the current map" icon="file_save.png"/>
+ <separator/>
+ <toolbutton name="changeviews" action="NextView" tooltip="Change views" icon="view_change.png"/>
+ <toggletoolbutton name="cubicclip" action="ToggleCubicClip" tooltip="Cubic clip the camera view" icon="view_cubicclipping.png"/>
+ <separator/>
+ <toolbutton name="selectcompletetall" action="SelectCompleteTall" tooltip="Select complete tall" icon="selection_selectcompletetall.png" />
+ <toolbutton name="selecttouching" action="SelectTouching" tooltip="Select touching" icon="selection_selecttouching.png"/>
+ <toolbutton name="selectinside" action="SelectInside" tooltip="Select inside" icon="selection_selectinside.png"/>
+ <separator/>
+ <toggletoolbutton name="dragvertices" action="DragVertices" tooltip="Select Vertices" icon="modify_vertices.png"/>
+ <toggletoolbutton name="dragedges" action="DragEdges" tooltip="Select Edges" icon="modify_edges.png"/>
+ <toggletoolbutton name="dragfaces" action="DragFaces" tooltip="Select Faces" icon="modify_faces.png"/>
+ <toggletoolbutton name="dragentities" action="DragEntities" tooltip="Select Entities" icon="select_entities.png"/>
+ <toggletoolbutton name="selectionModeGroupPart" action="SelectionModeGroupPart" tooltip="Select Group Parts" icon="select_group_parts.png"/>
+ <separator/>
+ <toggletoolbutton name="showlightradii" action="ToggleShowAllLightRadii" tooltip="Show/hide all light volumes" icon="view_show_lightradii.png"/>
+ <toggletoolbutton name="showspeakerradii" action="ToggleShowAllSpeakerRadii" tooltip="Show/hide all speaker volumes" icon="view_show_speakerradii.png"/>
+ <separator/>
+ <toggletoolbutton name="texturelock" action="TogTexLock" tooltip="Texture Lock" icon="texture_lock.png"/>
+ <toggletoolbutton name="freeobjectrotation" action="ToggleFreeObjectRotation" tooltip="Rotate Objects independently" icon="free_model_rotation.png" />
+ <toggletoolbutton name="togglerotationpivot" action="ToggleRotationPivot" tooltip="Rotate func_* Entities around origin" icon="rotation_pivot_origin.png" />
+ <toggletoolbutton name="dragresizesymm" action="ToggleDragResizeEntitiesSymmetrically" tooltip="Drag-resize entities symmetrically (leave origin unchanged)" icon="dragresize_symm.png" />
+ <toggletoolbutton name="offsetclones" action="ToggleOffsetClones" tooltip="Offset cloned objects by one grid unit to the right and downwards." icon="offset_clone.png" />
+ <separator/>
+ <toolbutton name="createDecals" action="CreateDecalsForFaces" tooltip="Create Decals for selected Faces" icon="create_decals.png"/>
+ </toolbar>
+ <toolbar name="edit" align="vertical">
+ <toolbutton name="xflip" action="MirrorSelectionX" tooltip="x-axis Mirror" icon="brush_flipx.png"/>
+ <toolbutton name="xrotate" action="RotateSelectionX" tooltip="x-axis Rotate" icon="brush_rotatex.png"/>
+ <toolbutton name="yflip" action="MirrorSelectionY" tooltip="y-axis Mirror" icon="brush_flipy.png"/>
+ <toolbutton name="yrotate" action="RotateSelectionY" tooltip="y-axis Rotate" icon="brush_rotatey.png"/>
+ <toolbutton name="zflip" action="MirrorSelectionZ" tooltip="z-axis Mirror" icon="brush_flipz.png"/>
+ <toolbutton name="zrotate" action="RotateSelectionZ" tooltip="z-axis Rotate" icon="brush_rotatez.png"/>
+ <separator/>
+ <toolbutton name="snaptogrid" action="SnapToGrid" tooltip="Snap selection to grid" icon="grid_snap.png"/>
<toolbutton name="floorselected" action="FloorSelection" tooltip="Floor selection" icon="floorSelected.png"/>
- <separator/>
- <toggletoolbutton name="translate" action="MouseTranslate" tooltip="Translate" icon="select_mousetranslate.png"/>
- <toggletoolbutton name="rotate" action="MouseRotate" tooltip="Rotate" icon="select_mouserotate.png"/>
- <toggletoolbutton name="resize" action="MouseDrag" tooltip="Resize" icon="select_mouseresize.png"/>
- <toggletoolbutton name="clipper" action="ToggleClipper" tooltip="Clipper" icon="view_clipper.png"/>
- <separator/>
- <toolbutton name="csgsubstract" action="CSGSubtract" tooltip="CSG Subtract" icon="selection_csgsubtract.png"/>
- <toolbutton name="csgmerge" action="CSGMerge" tooltip="CSG Merge" icon="selection_csgmerge.png"/>
- <toolbutton name="csghollow" action="CSGHollow" tooltip="Hollow" icon="selection_makehollow.png"/>
- <toolbutton name="csgroom" action="CSGRoom" tooltip="Make Room" icon="selection_makeroom.png"/>
- <separator/>
- <toolbutton name="capcurrentcurve" action="CapCurrentCurve" tooltip="Put caps on the current patch" icon="curve_cap.png"/>
- <separator/>
- <toolbutton name="curvecreate" action="CreateCurveNURBS" tooltip="Creates a NURBS curve" icon="curve_create.png"/>
- <toolbutton name="curveconvert" action="CurveConvertType" tooltip="Convert the selected curve (NURBS <-> CatmullRom)" icon="curve_convert.png"/>
- <toolbutton name="curveappendpoint" action="CurveAppendControlPoint" tooltip="Appends a control point to the selected curves" icon="curve_append_point.png"/>
- <toolbutton name="curveinsertpoint" action="CurveInsertControlPoint" tooltip="Inserts a curve control point before the selected ones" icon="curve_insert_points.png"/>
- <toolbutton name="curveremovepoint" action="CurveRemoveControlPoint" tooltip="Removes the selected curve control points" icon="curve_remove_points.png"/>
- </toolbar>
- <toolbar name="texture" align="horizontal">
- <toolbutton name="flush" action="RefreshShaders" tooltip="Reload Materials" icon="texwindow_flushandreload.png"/>
- <toggletoolbutton name="showinuse" action="ShowInUse" tooltip="Hide Unused" icon="texwindow_hideunused.png"/>
- <separator/>
- <toolbutton name="findandreplace" action="FindReplaceTextures" tooltip="Find & Replace" icon="texwindow_findandreplace.png"/>
+ <separator/>
+ <toggletoolbutton name="translate" action="MouseTranslate" tooltip="Translate" icon="select_mousetranslate.png"/>
+ <toggletoolbutton name="rotate" action="MouseRotate" tooltip="Rotate" icon="select_mouserotate.png"/>
+ <toggletoolbutton name="resize" action="MouseDrag" tooltip="Resize" icon="select_mouseresize.png"/>
+ <toggletoolbutton name="clipper" action="ToggleClipper" tooltip="Clipper" icon="view_clipper.png"/>
+ <separator/>
+ <toolbutton name="csgsubstract" action="CSGSubtract" tooltip="CSG Subtract" icon="selection_csgsubtract.png"/>
+ <toolbutton name="csgmerge" action="CSGMerge" tooltip="CSG Merge" icon="selection_csgmerge.png"/>
+ <toolbutton name="csghollow" action="CSGHollow" tooltip="Hollow" icon="selection_makehollow.png"/>
+ <toolbutton name="csgroom" action="CSGRoom" tooltip="Make Room" icon="selection_makeroom.png"/>
+ <separator/>
+ <toolbutton name="groupSelected" action="GroupSelected" tooltip="Group selected items" icon="group_selection.png"/>
+ <toolbutton name="unGroupSelected" action="UngroupSelected" tooltip="Ungroup selected items" icon="ungroup_selection.png"/>
+ <separator/>
+ <toolbutton name="capcurrentcurve" action="CapCurrentCurve" tooltip="Put caps on the current patch" icon="curve_cap.png"/>
+ <separator/>
+ <toolbutton name="curvecreate" action="CreateCurveNURBS" tooltip="Creates a NURBS curve" icon="curve_create.png"/>
+ <toolbutton name="curveconvert" action="CurveConvertType" tooltip="Convert the selected curve (NURBS <-> CatmullRom)" icon="curve_convert.png"/>
+ <toolbutton name="curveappendpoint" action="CurveAppendControlPoint" tooltip="Appends a control point to the selected curves" icon="curve_append_point.png"/>
+ <toolbutton name="curveinsertpoint" action="CurveInsertControlPoint" tooltip="Inserts a curve control point before the selected ones" icon="curve_insert_points.png"/>
+ <toolbutton name="curveremovepoint" action="CurveRemoveControlPoint" tooltip="Removes the selected curve control points" icon="curve_remove_points.png"/>
+ </toolbar>
+ <toolbar name="texture" align="horizontal">
+ <toolbutton name="flush" action="RefreshShaders" tooltip="Reload Materials" icon="texwindow_flushandreload.png"/>
+ <toggletoolbutton name="showinuse" action="ShowInUse" tooltip="Hide Unused" icon="texwindow_hideunused.png"/>
+ <separator/>
+ <toolbutton name="findandreplace" action="FindReplaceTextures" tooltip="Find & Replace" icon="texwindow_findandreplace.png"/>
</toolbar>
- <toolbar name="textool" align="horizontal">
- <toolbutton name="griddown" action="TexToolGridDown" tooltip="Decrease Grid Size" icon="grid_down.png"/>
- <toolbutton name="gridup" action="TexToolGridUp" tooltip="Increase Grid Size" icon="grid_up.png"/>
- <toolbutton name="gridsnap" action="TexToolSnapToGrid" tooltip="Snap to Grid" icon="grid_snap.png"/>
- <toggletoolbutton name="usegrid" action="TexToolToggleGrid" tooltip="Toggle Grid" icon="grid_toggle.png"/>
- <separator/>
- <toolbutton name="mergeitems" action="TexToolMergeItems" tooltip="Merge Selection" icon="textool_merge.png"/>
- <toolbutton name="texflips" action="TexToolFlipS" tooltip="Flip Selection Horiz (S-Axis)" icon="tex_flips.png"/>
- <toolbutton name="texflipt" action="TexToolFlipT" tooltip="Flip Selection Vertical (T-Axis)" icon="tex_flipt.png"/>
- <toolbutton name="selectrelated" action="TexToolSelectRelated" tooltip="Select Related Items" icon="textool_select_related.png"/>
- <separator/>
- <toggletoolbutton name="togglefacevertexscalepivot" action="TexToolToggleFaceVertexScalePivot" tooltip="Center Pivot when scaling faces" icon="textool_facescale_pivot.png"/>
+ <toolbar name="textool" align="horizontal">
+ <toolbutton name="griddown" action="TexToolGridDown" tooltip="Decrease Grid Size" icon="grid_down.png"/>
+ <toolbutton name="gridup" action="TexToolGridUp" tooltip="Increase Grid Size" icon="grid_up.png"/>
+ <toolbutton name="gridsnap" action="TexToolSnapToGrid" tooltip="Snap to Grid" icon="grid_snap.png"/>
+ <toggletoolbutton name="usegrid" action="TexToolToggleGrid" tooltip="Toggle Grid" icon="grid_toggle.png"/>
+ <separator/>
+ <toolbutton name="mergeitems" action="TexToolMergeItems" tooltip="Merge Selection" icon="textool_merge.png"/>
+ <toolbutton name="texflips" action="TexToolFlipS" tooltip="Flip Selection Horiz (S-Axis)" icon="tex_flips.png"/>
+ <toolbutton name="texflipt" action="TexToolFlipT" tooltip="Flip Selection Vertical (T-Axis)" icon="tex_flipt.png"/>
+ <toolbutton name="selectrelated" action="TexToolSelectRelated" tooltip="Select Related Items" icon="textool_select_related.png"/>
+ <separator/>
+ <toggletoolbutton name="togglefacevertexscalepivot" action="TexToolToggleFaceVertexScalePivot" tooltip="Center Pivot when scaling faces" icon="textool_facescale_pivot.png"/>
</toolbar>
- </ui>
+ </ui>
</user>
diff --git a/libs/ObservedSelectable.h b/libs/ObservedSelectable.h
index 8310338..4b69a3a 100644
--- a/libs/ObservedSelectable.h
+++ b/libs/ObservedSelectable.h
@@ -12,7 +12,7 @@ namespace selection
* callback function when the selection state is changed.
*/
class ObservedSelectable :
- public Selectable
+ public ISelectable
{
// Callback to invoke on selection changed
SelectionChangedSlot _onchanged;
@@ -36,7 +36,7 @@ public:
* Copy constructor.
*/
ObservedSelectable(const ObservedSelectable& other) :
- Selectable(other),
+ ISelectable(other),
_onchanged(other._onchanged),
_selected(false)
{
@@ -58,7 +58,7 @@ public:
* \brief
* Set the selection state.
*/
- virtual void setSelected(bool select)
+ virtual void setSelected(bool select) override
{
// Change state and invoke callback only if the new state is different
// from the current state
@@ -73,15 +73,10 @@ public:
}
}
- virtual bool isSelected() const
+ virtual bool isSelected() const override
{
return _selected;
}
-
- virtual void invertSelected()
- {
- setSelected(!isSelected());
- }
};
} // namespace
diff --git a/libs/SelectableNode.h b/libs/SelectableNode.h
deleted file mode 100644
index 3046a70..0000000
--- a/libs/SelectableNode.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include "scene/Node.h"
-#include "ObservedSelectable.h"
-#include <functional>
-
-namespace scene
-{
-
-/**
- * \brief
- * Subclass of scene::Node which implements the Selectable interface.
- *
- * The GlobalSelectionSystem will be notified of selection changes.
- */
-class SelectableNode :
- public scene::Node,
- public selection::ObservedSelectable
-{
-public:
- SelectableNode() :
- ObservedSelectable(std::bind(&SelectableNode::selectedChanged, this, std::placeholders::_1))
- {}
-
- // The copy-constructor doesn't copy the signal, re-connect to this instance instead
- SelectableNode(const SelectableNode& other) :
- scene::Node(other),
- ObservedSelectable(std::bind(&SelectableNode::selectedChanged, this, std::placeholders::_1))
- {}
-
- virtual ~SelectableNode() {}
-
- // override scene::Inode::onRemoveFromScene to de-select self
- virtual void onRemoveFromScene(IMapRootNode& root) override
- {
- setSelected(false);
-
- Node::onRemoveFromScene(root);
- }
-
-private:
- /**
- * \brief
- * Callback invoked by the ObservedSelectable when the selection changes.
- */
- void selectedChanged(const Selectable& selectable)
- {
- GlobalSelectionSystem().onSelectedChanged(Node::getSelf(), selectable);
- }
-};
-
-} // namespace
diff --git a/libs/entitylib.h b/libs/entitylib.h
index 4658aad..cee9ef5 100644
--- a/libs/entitylib.h
+++ b/libs/entitylib.h
@@ -307,6 +307,10 @@ public:
{
aabb_draw_solid(m_aabb, info.getFlags());
}
+ const AABB& getAABB() const
+ {
+ return m_aabb;
+ }
};
class RenderableWireframeAABB : public OpenGLRenderable
@@ -398,9 +402,11 @@ inline Entity* Scene_FindEntityByClass(const std::string& className)
/* Check if a node is the worldspawn.
*/
-inline bool node_is_worldspawn(const scene::INodePtr& node) {
+inline bool Node_isWorldspawn(const scene::INodePtr& node)
+{
Entity* entity = Node_getEntity(node);
- return entity != 0 && entity->getKeyValue("classname") == "worldspawn";
+
+ return entity != nullptr && entity->isWorldspawn();
}
/**
diff --git a/libs/math/Vector2.h b/libs/math/Vector2.h
index df377c2..824ad97 100644
--- a/libs/math/Vector2.h
+++ b/libs/math/Vector2.h
@@ -305,6 +305,12 @@ public:
Element crossProduct(const BasicVector2<OtherT>& other) const {
return Element(_v[0] * other.y() - _v[1] * other.x());
}
+
+ // Returns the mid-point of this vector and the other one
+ BasicVector2<Element> mid(const BasicVector2<Element>& other) const
+ {
+ return (*this + other) * 0.5f;
+ }
};
// ==========================================================================================
diff --git a/libs/os/file.h b/libs/os/file.h
index 2fa759e..300a87d 100644
--- a/libs/os/file.h
+++ b/libs/os/file.h
@@ -1,26 +1,4 @@
-/*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
-
-This file is part of GtkRadiant.
-
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-GtkRadiant 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#if !defined(INCLUDED_OS_FILE_H)
-#define INCLUDED_OS_FILE_H
+#pragma once
/// \file
/// \brief OS file-system querying and manipulation.
@@ -47,32 +25,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <cstddef>
#include <ctime>
+#include "itextstream.h"
+#include <boost/filesystem/operations.hpp>
#include "debugging/debugging.h"
-/// \brief Attempts to move the file identified by \p from to \p to and returns true if the operation was successful.
-///
-/// The operation will fail unless:
-/// - The path \p from identifies an existing file which is accessible for writing.
-/// - The directory component of \p from identifies an existing directory which is accessible for writing.
-/// - The path \p to does not identify an existing file or directory.
-/// - The directory component of \p to identifies an existing directory which is accessible for writing.
-inline bool file_move(const char* from, const char* to)
-{
- ASSERT_MESSAGE(from != 0 && to != 0, "file_move: invalid path");
- return rename(from, to) == 0;
-}
-
-/// \brief Attempts to remove the file identified by \p path and returns true if the operation was successful.
-///
-/// The operation will fail unless:
-/// - The \p path identifies an existing file.
-/// - The parent-directory component of \p path identifies an existing directory which is accessible for writing.
-inline bool file_remove(const char* path)
-{
- ASSERT_MESSAGE(path != 0, "file_remove: invalid path");
- return remove(path) == 0;
-}
-
namespace FileAccess
{
enum Mode
@@ -112,51 +68,18 @@ inline bool fileOrDirExists(const std::string& path)
return file_accessible(path.c_str(), FileAccess::Exists);
}
-}
-
-/// \brief Returns true if the file or directory identified by \p path exists and is a directory.
-inline bool file_is_directory(const char* path)
+// Returns the file size in bytes, or static_cast<uintmax_t>(-1)
+inline std::size_t getFileSize(const std::string& path)
{
- ASSERT_MESSAGE(path != 0, "file_is_directory: invalid path");
- struct stat st;
- if(stat(path, &st) == -1)
- {
- return false;
- }
- return S_ISDIR (st.st_mode) != 0;
+ try
+ {
+ return static_cast<std::size_t>(boost::filesystem::file_size(path));
+ }
+ catch (boost::filesystem::filesystem_error& err)
+ {
+ rError() << "Error checking filesize: " << err.what() << std::endl;
+ return static_cast<std::size_t>(-1);
+ }
}
-typedef std::size_t FileSize;
-
-/// \brief Returns the size in bytes of the file identified by \p path, or 0 if the file was not found.
-inline FileSize file_size(const char* path)
-{
- ASSERT_MESSAGE(path != 0, "file_size: invalid path");
- struct stat st;
- if(stat(path, &st) == -1)
- {
- return 0;
- }
- return st.st_size;
-}
-
-/// Seconds elapsed since Jan 1, 1970
-typedef std::time_t FileTime;
-/// No file can have been modified earlier than this time.
-const FileTime c_invalidFileTime = -1;
-
-/// \brief Returns the time that the file identified by \p path was last modified, or c_invalidFileTime if the file was not found.
-inline FileTime file_modified(const char* path)
-{
- ASSERT_MESSAGE(path != 0, "file_modified: invalid path");
- struct stat st;
- if(stat(path, &st) == -1)
- {
- return c_invalidFileTime;
- }
- return st.st_mtime;
-}
-
-
-
-#endif
+} // namespace
diff --git a/libs/os/path.h b/libs/os/path.h
index fc213e6..8ebb03b 100644
--- a/libs/os/path.h
+++ b/libs/os/path.h
@@ -18,9 +18,7 @@ You should have received a copy of the GNU General Public License
along with GtkRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
-#if !defined (INCLUDED_OS_PATH_H)
-#define INCLUDED_OS_PATH_H
+#pragma once
/// \file
/// \brief OS file-system path comparison, decomposition and manipulation.
@@ -66,17 +64,6 @@ inline int path_compare(const char* path, const char* other)
#endif
}
-/// \brief Returns true if \p path and \p other refer to the same file or directory.
-/// O(n)
-inline bool path_equal(const char* path, const char* other)
-{
-#if defined(OS_CASE_INSENSITIVE)
- return string_equal_nocase(path, other);
-#else
- return string_equal(path, other);
-#endif
-}
-
/// \brief Returns true if the first \p n bytes of \p path and \p other form paths that refer to the same file or directory.
/// If the paths are UTF-8 encoded, [\p path, \p path + \p n) must be a complete path.
/// O(n)
@@ -278,6 +265,3 @@ namespace os
return trimmed.substr(lastSlash + 1);
}
}
-
-
-#endif
diff --git a/libs/pivot.h b/libs/pivot.h
index d0b36fd..2e2d52f 100644
--- a/libs/pivot.h
+++ b/libs/pivot.h
@@ -300,7 +300,7 @@ public:
// greebo: Commented this out to avoid the point from being moved along with the view.
//Pivot2World_worldSpace(m_localToWorld, localToWorld, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
- collector.highlightPrimitives(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
collector.SetState(_shader, RenderableCollector::eWireframeOnly);
collector.SetState(_shader, RenderableCollector::eFullMaterials);
collector.addRenderable(*this, localToWorld);
diff --git a/libs/registry/Widgets.h b/libs/registry/Widgets.h
index b104cc3..b5660e3 100644
--- a/libs/registry/Widgets.h
+++ b/libs/registry/Widgets.h
@@ -4,6 +4,7 @@
#include <wx/textctrl.h>
#include <wx/checkbox.h>
#include <wx/slider.h>
+#include <wx/tglbtn.h>
#include <wx/choice.h>
#include "registry.h"
@@ -66,13 +67,28 @@ inline void bindWidget(wxCheckBox* checkbox, const std::string& key)
});
}
+inline void bindWidget(wxToggleButton* toggleButton, const std::string& key)
+{
+ // Set initial value then connect to changed signal
+ if (GlobalRegistry().keyExists(key))
+ {
+ toggleButton->SetValue(registry::getValue<bool>(key));
+ }
+
+ toggleButton->Bind(wxEVT_TOGGLEBUTTON, [=](wxCommandEvent& ev)
+ {
+ registry::setValue(key, toggleButton->GetValue() ? "1" : "0");
+ ev.Skip();
+ });
+}
+
// ------------- Variants supporting registry::Buffer ---------------------
inline void bindWidgetToBufferedKey(wxCheckBox* checkbox, const std::string& key,
Buffer& buffer, sigc::signal<void>& resetSignal)
{
// Set initial value then connect to changed signal
- checkbox->SetValue(GlobalRegistry().get(key) == "1");
+ checkbox->SetValue(registry::getValue<std::string>(key) == "1");
checkbox->Bind(wxEVT_CHECKBOX, [=, &buffer] (wxCommandEvent& ev)
{
@@ -80,7 +96,7 @@ inline void bindWidgetToBufferedKey(wxCheckBox* checkbox, const std::string& key
ev.Skip();
});
- resetSignal.connect([=, &buffer] { if (buffer.keyExists(key)) { checkbox->SetValue(buffer.get(key) == "1"); } });
+ resetSignal.connect([=, &buffer] { if (buffer.keyExists(key)) { checkbox->SetValue(registry::getValue<std::string>(key) == "1"); } });
}
inline void bindWidgetToBufferedKey(wxSlider* slider, const std::string& key,
@@ -100,7 +116,13 @@ inline void bindWidgetToBufferedKey(wxSlider* slider, const std::string& key,
ev.Skip();
});
- resetSignal.connect([=, &buffer] { if (buffer.keyExists(key)) { slider->SetValue(registry::getValue<float>(key) * factor); } });
+ resetSignal.connect([=, &buffer]
+ {
+ if (buffer.keyExists(key))
+ {
+ slider->SetValue(registry::getValue<float>(key) * factor);
+ }
+ });
}
inline void bindWidgetToBufferedKey(wxChoice* choice, const std::string& key,
diff --git a/libs/render/RenderableSpacePartition.h b/libs/render/RenderableSpacePartition.h
index ea0c0b1..282c2b7 100644
--- a/libs/render/RenderableSpacePartition.h
+++ b/libs/render/RenderableSpacePartition.h
@@ -37,7 +37,7 @@ public:
_spacePartition = spacePartition;
}
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override
{
if (_shader != NULL)
{
@@ -46,7 +46,7 @@ public:
}
}
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override
{
if (_shader != NULL)
{
@@ -55,7 +55,7 @@ public:
}
}
- void setRenderSystem(const RenderSystemPtr& renderSystem)
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override
{
if (renderSystem)
{
@@ -67,9 +67,9 @@ public:
}
}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
void renderNode(const scene::ISPNodePtr& node) const
diff --git a/libs/render/ShaderStateRenderer.h b/libs/render/ShaderStateRenderer.h
index ecf44f0..ed98c43 100644
--- a/libs/render/ShaderStateRenderer.h
+++ b/libs/render/ShaderStateRenderer.h
@@ -80,9 +80,8 @@ public:
}
// No support for selection highlighting
- void highlightFaces(bool enable = true) { }
- void highlightPrimitives(bool enable = true) { }
-
+ void setHighlightFlag(Highlight::Flags flags, bool enabled) {}
+
void setLights(const LightList& lights)
{
_stateStack.back().lights = &lights;
diff --git a/libs/scene/BasicRootNode.h b/libs/scene/BasicRootNode.h
index 92bee69..042dc2e 100644
--- a/libs/scene/BasicRootNode.h
+++ b/libs/scene/BasicRootNode.h
@@ -64,9 +64,9 @@ public:
void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override
{}
- bool isHighlighted() const override
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
};
diff --git a/libs/scene/Makefile.am b/libs/scene/Makefile.am
index f65741d..f1a75f1 100644
--- a/libs/scene/Makefile.am
+++ b/libs/scene/Makefile.am
@@ -5,4 +5,5 @@ libscenegraph_la_LDFLAGS = -release @PACKAGE_VERSION@ $(LIBSIGC_LIBS)
libscenegraph_la_LIBADD = $(top_builddir)/libs/math/libmath.la
libscenegraph_la_SOURCES = InstanceWalkers.cpp \
TraversableNodeSet.cpp \
+ SelectableNode.cpp \
Node.cpp
diff --git a/libs/scene/Makefile.in b/libs/scene/Makefile.in
index d7d8cd7..1ce347e 100644
--- a/libs/scene/Makefile.in
+++ b/libs/scene/Makefile.in
@@ -128,7 +128,7 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)"
LTLIBRARIES = $(pkglib_LTLIBRARIES)
libscenegraph_la_DEPENDENCIES = $(top_builddir)/libs/math/libmath.la
am_libscenegraph_la_OBJECTS = InstanceWalkers.lo TraversableNodeSet.lo \
- Node.lo
+ SelectableNode.lo Node.lo
libscenegraph_la_OBJECTS = $(am_libscenegraph_la_OBJECTS)
AM_V_lt = $(am__v_lt_ at AM_V@)
am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -404,6 +404,7 @@ libscenegraph_la_LDFLAGS = -release @PACKAGE_VERSION@ $(LIBSIGC_LIBS)
libscenegraph_la_LIBADD = $(top_builddir)/libs/math/libmath.la
libscenegraph_la_SOURCES = InstanceWalkers.cpp \
TraversableNodeSet.cpp \
+ SelectableNode.cpp \
Node.cpp
all: all-am
@@ -487,6 +488,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/InstanceWalkers.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Node.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SelectableNode.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/TraversableNodeSet.Plo at am__quote@
.cpp.o:
diff --git a/libs/scene/Node.cpp b/libs/scene/Node.cpp
index fa7edea..3ce3d26 100644
--- a/libs/scene/Node.cpp
+++ b/libs/scene/Node.cpp
@@ -49,6 +49,7 @@ Node::Node() :
_transformMutex(false),
_local2world(Matrix4::getIdentity()),
_instantiated(false),
+ _forceVisible(false),
_renderEntity(nullptr)
{
// Each node is part of layer 0 by default
@@ -68,6 +69,7 @@ Node::Node(const Node& other) :
_childBoundsMutex(false),
_local2world(other._local2world),
_instantiated(false),
+ _forceVisible(false),
_layers(other._layers),
_renderEntity(other._renderEntity)
{}
@@ -118,7 +120,8 @@ bool Node::checkStateFlag(unsigned int state) const
bool Node::visible() const
{
// Only instantiated nodes can be considered visible
- return _state == eVisible && _instantiated;
+ // The force visible flag is allowed to override the regular status
+ return (_state == eVisible && _instantiated) || _forceVisible;
}
bool Node::excluded() const
@@ -170,7 +173,16 @@ void Node::addChildNode(const INodePtr& node)
// Add the node to the TraversableNodeSet, this triggers an
// Node::onChildAdded() event, where the parent of the new
// child is set, among other things
- _children.insert(node);
+ _children.append(node);
+}
+
+void Node::addChildNodeToFront(const INodePtr& node)
+{
+ // Add the node to the TraversableNodeSet at the front
+ // This behaves the same as addChildNode(), triggering a
+ // Node::onChildAdded() event, where the parent of the new
+ // child is set, among other things
+ _children.prepend(node);
}
void Node::removeChildNode(const INodePtr& node)
@@ -475,6 +487,25 @@ void Node::setRenderSystem(const RenderSystemPtr& renderSystem)
_children.setRenderSystem(renderSystem);
}
+void Node::setForcedVisibility(bool forceVisible, bool includeChildren)
+{
+ _forceVisible = forceVisible;
+
+ if (includeChildren)
+ {
+ _children.foreachNode([&](const INodePtr& node)
+ {
+ node->setForcedVisibility(forceVisible, includeChildren);
+ return true;
+ });
+ }
+}
+
+bool Node::isForcedVisible() const
+{
+ return _forceVisible;
+}
+
unsigned long Node::_maxNodeId = 0;
} // namespace scene
diff --git a/libs/scene/Node.h b/libs/scene/Node.h
index 15f805e..feb9ef7 100644
--- a/libs/scene/Node.h
+++ b/libs/scene/Node.h
@@ -57,6 +57,10 @@ private:
// Is true when the node is part of the scenegraph
bool _instantiated;
+ // A special flag capable of overriding the ordinary state flags
+ // We use this to force the rendering of hidden but selected nodes
+ bool _forceVisible;
+
// The list of layers this object is associated to
LayerList _layers;
@@ -94,6 +98,9 @@ public:
bool visible() const override;
bool excluded() const override;
+ // Set the "forced visible" flag, only to be used internally by subclasses
+ void setForcedVisibility(bool forceVisible, bool includeChildren) override;
+
// Layered implementation
virtual void addToLayer(int layerId);
virtual void removeFromLayer(int layerId);
@@ -101,9 +108,10 @@ public:
virtual LayerList getLayers() const;
virtual void assignToLayers(const LayerList& newLayers);
- virtual void addChildNode(const INodePtr& node);
- virtual void removeChildNode(const INodePtr& node);
- virtual bool hasChildNodes() const;
+ virtual void addChildNode(const INodePtr& node) override;
+ virtual void addChildNodeToFront(const INodePtr& node) override;
+ virtual void removeChildNode(const INodePtr& node) override;
+ virtual bool hasChildNodes() const override;
virtual void traverse(NodeVisitor& visitor);
virtual void traverseChildren(NodeVisitor& visitor) const;
@@ -187,6 +195,9 @@ public:
virtual void setRenderSystem(const RenderSystemPtr& renderSystem);
protected:
+ // Method for subclasses to check whether this node is forcedly visible
+ bool isForcedVisible() const;
+
// Fills in the ancestors and self (in this order) into the given targetPath.
void getPathRecursively(scene::Path& targetPath);
diff --git a/libs/scene/SelectableNode.cpp b/libs/scene/SelectableNode.cpp
new file mode 100644
index 0000000..48677a7
--- /dev/null
+++ b/libs/scene/SelectableNode.cpp
@@ -0,0 +1,247 @@
+#include "SelectableNode.h"
+
+#include "iselection.h"
+#include "BasicUndoMemento.h"
+#include "imap.h"
+#include <stdexcept>
+#include <algorithm>
+#include <iterator>
+
+namespace scene
+{
+
+SelectableNode::SelectableNode() :
+ _selected(false),
+ _undoStateSaver(nullptr)
+{}
+
+SelectableNode::SelectableNode(const SelectableNode& other) :
+ scene::Node(other),
+ _selected(false),
+ _undoStateSaver(nullptr)
+{}
+
+SelectableNode::~SelectableNode()
+{
+ setSelected(false);
+}
+
+void SelectableNode::onInsertIntoScene(IMapRootNode& root)
+{
+ connectUndoSystem(root.getUndoChangeTracker());
+
+ Node::onInsertIntoScene(root);
+
+ // If the group ID set is not empty, this node was likely removed while
+ // it was still member of one or more groups.
+ // Try to add ourselves to any groups we were assigned to, if the group
+ // is not there anymore, it will be created.
+ for (std::size_t id : _groups)
+ {
+ selection::ISelectionGroupPtr group = GlobalSelectionGroupManager().findOrCreateSelectionGroup(id);
+
+ if (group)
+ {
+ group->addNode(getSelf());
+ }
+ }
+}
+
+void SelectableNode::onRemoveFromScene(IMapRootNode& root)
+{
+ setSelected(false);
+
+ disconnectUndoSystem(root.getUndoChangeTracker());
+
+ // When a node is removed from the scene with a non-empty group assignment
+ // we do notify the SelectionGroup to remove ourselves, but we keep the ID list
+ // That way we can re-add ourselves when being inserted into the scene again
+
+ if (!_groups.empty())
+ {
+ // Copy the group IDs, as calling removeNode() will alter the group ID list
+ GroupIds copy(_groups);
+
+ // Remove ourselves from all groups
+ while (!_groups.empty())
+ {
+ std::size_t id = _groups.front();
+
+ selection::ISelectionGroupPtr group = GlobalSelectionGroupManager().getSelectionGroup(id);
+
+ if (group)
+ {
+ group->removeNode(getSelf());
+ }
+ else
+ {
+ _groups.erase(_groups.begin());
+ }
+ }
+
+ // Now copy the values back in for later use
+ _groups.swap(copy);
+ }
+
+ Node::onRemoveFromScene(root);
+}
+
+void SelectableNode::setSelected(bool select)
+{
+ // Set selection status and notify group members if applicable
+ setSelected(select, false);
+}
+
+void SelectableNode::addToGroup(std::size_t groupId)
+{
+ if (std::find(_groups.begin(), _groups.end(), groupId) == _groups.end())
+ {
+ undoSave();
+
+ _groups.push_back(groupId);
+ }
+}
+
+void SelectableNode::removeFromGroup(std::size_t groupId)
+{
+ std::vector<std::size_t>::iterator i = std::find(_groups.begin(), _groups.end(), groupId);
+
+ if (i != _groups.end())
+ {
+ undoSave();
+
+ _groups.erase(i);
+ }
+}
+
+bool SelectableNode::isGroupMember()
+{
+ return !_groups.empty();
+}
+
+std::size_t SelectableNode::getMostRecentGroupId()
+{
+ if (_groups.empty()) throw std::runtime_error("This node is not a member of any group.");
+
+ return _groups.back();
+}
+
+const SelectableNode::GroupIds& SelectableNode::getGroupIds()
+{
+ return _groups;
+}
+
+void SelectableNode::setSelected(bool select, bool changeGroupStatus)
+{
+ // Change state and invoke callback only if the new state is different
+ // from the current state
+ if (select ^ _selected)
+ {
+ _selected = select;
+
+ onSelectionStatusChange(changeGroupStatus);
+ }
+}
+
+bool SelectableNode::isSelected() const
+{
+ return _selected;
+}
+
+IUndoMementoPtr SelectableNode::exportState() const
+{
+ return IUndoMementoPtr(new undo::BasicUndoMemento<GroupIds>(_groups));
+}
+
+void SelectableNode::importState(const IUndoMementoPtr& state)
+{
+ undoSave();
+
+ // Process the incoming set difference
+ GroupIds newGroups = std::static_pointer_cast< undo::BasicUndoMemento<GroupIds> >(state)->data();
+
+ // The set_difference algorithm requires the sets to be sorted
+ std::sort(_groups.begin(), _groups.end());
+ std::sort(newGroups.begin(), newGroups.end());
+
+ GroupIds removedGroups;
+ std::set_difference(_groups.begin(), _groups.end(), newGroups.begin(), newGroups.end(),
+ std::inserter(removedGroups, removedGroups.begin()));
+
+ GroupIds addedGroups;
+ std::set_difference(newGroups.begin(), newGroups.end(), _groups.begin(), _groups.end(),
+ std::inserter(addedGroups, addedGroups.begin()));
+
+ // Remove ourselves from each removed group ID
+ for (GroupIds::value_type id : removedGroups)
+ {
+ selection::ISelectionGroupPtr group = GlobalSelectionGroupManager().getSelectionGroup(id);
+
+ if (group)
+ {
+ group->removeNode(getSelf());
+ }
+ }
+
+ // Add ourselves to each missing group ID
+ for (GroupIds::value_type id : addedGroups)
+ {
+ selection::ISelectionGroupPtr group = GlobalSelectionGroupManager().findOrCreateSelectionGroup(id);
+
+ assert(group);
+ group->addNode(getSelf());
+ }
+
+ // The _groups array should now contain the same elements as the imported ones
+#if _DEBUG
+ std::sort(_groups.begin(), _groups.end());
+ assert(std::equal(_groups.begin(), _groups.end(), newGroups.begin()));
+#endif
+
+ // After undoing group assignments, highlight this node for better user feedback
+ setSelected(true, false);
+}
+
+void SelectableNode::onSelectionStatusChange(bool changeGroupStatus)
+{
+ bool selected = isSelected();
+
+ // Update the flag to render selected nodes regardless of their hidden status
+ setForcedVisibility(selected, true);
+
+ GlobalSelectionSystem().onSelectedChanged(Node::getSelf(), *this);
+
+ // Check if this node is member of a group
+ if (changeGroupStatus && !_groups.empty())
+ {
+ std::size_t mostRecentGroupId = _groups.back();
+
+ // Propagate the selection status of this node to all members of the topmost group
+ GlobalSelectionGroupManager().setGroupSelected(mostRecentGroupId, selected);
+ }
+}
+
+void SelectableNode::connectUndoSystem(IMapFileChangeTracker& changeTracker)
+{
+ _undoStateSaver = GlobalUndoSystem().getStateSaver(*this, changeTracker);
+
+ Node::connectUndoSystem(changeTracker);
+}
+
+void SelectableNode::disconnectUndoSystem(IMapFileChangeTracker& changeTracker)
+{
+ _undoStateSaver = nullptr;
+ GlobalUndoSystem().releaseStateSaver(*this);
+
+ Node::disconnectUndoSystem(changeTracker);
+}
+
+void SelectableNode::undoSave()
+{
+ if (_undoStateSaver != nullptr)
+ {
+ _undoStateSaver->save(*this);
+ }
+}
+
+} // namespace
diff --git a/libs/scene/SelectableNode.h b/libs/scene/SelectableNode.h
new file mode 100644
index 0000000..798b17f
--- /dev/null
+++ b/libs/scene/SelectableNode.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "scene/Node.h"
+#include "iselectiongroup.h"
+#include "iundo.h"
+
+namespace scene
+{
+
+/**
+ * \brief
+ * Subclass of scene::Node which implements the Selectable interface.
+ *
+ * The GlobalSelectionSystem will be notified of selection changes.
+ */
+class SelectableNode :
+ public scene::Node,
+ public IGroupSelectable,
+ public IUndoable
+{
+private:
+ // Current selection state
+ bool _selected;
+
+ // The groups this node is a member of. The last value in the list
+ // represents the group this node has been added to most recently
+ GroupIds _groups;
+
+ IUndoStateSaver* _undoStateSaver;
+
+public:
+ SelectableNode();
+
+ SelectableNode(const SelectableNode& other);
+
+ virtual ~SelectableNode();
+
+ virtual void onInsertIntoScene(IMapRootNode& root) override;
+
+ // override scene::Inode::onRemoveFromScene to de-select self
+ virtual void onRemoveFromScene(IMapRootNode& root) override;
+
+ /**
+ * \brief
+ * Set the selection state.
+ */
+ virtual void setSelected(bool select) override;
+
+ virtual void addToGroup(std::size_t groupId) override;
+ virtual void removeFromGroup(std::size_t groupId) override;
+
+ virtual bool isGroupMember() override;
+ virtual std::size_t getMostRecentGroupId() override;
+ virtual const GroupIds& getGroupIds() override;
+ virtual void setSelected(bool select, bool changeGroupStatus) override;
+ virtual bool isSelected() const override;
+
+ IUndoMementoPtr exportState() const override;
+ void importState(const IUndoMementoPtr& state) override;
+
+protected:
+ /**
+ * \brief
+ * Invoked when the selection status changes.
+ */
+ virtual void onSelectionStatusChange(bool changeGroupStatus);
+
+ virtual void connectUndoSystem(IMapFileChangeTracker& changeTracker) override;
+ virtual void disconnectUndoSystem(IMapFileChangeTracker& changeTracker) override;
+
+private:
+ void undoSave();
+};
+
+} // namespace
diff --git a/libs/scene/TraversableNodeSet.cpp b/libs/scene/TraversableNodeSet.cpp
index 3a451f8..7f29785 100644
--- a/libs/scene/TraversableNodeSet.cpp
+++ b/libs/scene/TraversableNodeSet.cpp
@@ -104,7 +104,7 @@ TraversableNodeSet::~TraversableNodeSet()
notifyEraseAll();
}
-void TraversableNodeSet::insert(const INodePtr& node)
+void TraversableNodeSet::append(const INodePtr& node)
{
// Submit the UndoMemento to the UndoSystem
undoSave();
@@ -116,6 +116,18 @@ void TraversableNodeSet::insert(const INodePtr& node)
_owner.onChildAdded(node);
}
+void TraversableNodeSet::prepend(const INodePtr& node)
+{
+ // Submit the UndoMemento to the UndoSystem
+ undoSave();
+
+ // Insert the child node at the front of the list
+ _children.push_front(node);
+
+ // Notify the owner (note: this usually triggers instantiation of the node)
+ _owner.onChildAdded(node);
+}
+
void TraversableNodeSet::erase(const INodePtr& node)
{
undoSave();
diff --git a/libs/scene/TraversableNodeSet.h b/libs/scene/TraversableNodeSet.h
index 0873a59..40b2f2a 100644
--- a/libs/scene/TraversableNodeSet.h
+++ b/libs/scene/TraversableNodeSet.h
@@ -48,9 +48,16 @@ public:
~TraversableNodeSet();
/**
- * greebo: This inserts a child node, saves the Undo state and notifies the owning node.
+ * greebo: This inserts a child node at the end of the list,
+ * saves the Undo state and notifies the owning node.
*/
- void insert(const INodePtr& node);
+ void append(const INodePtr& node);
+
+ /**
+ * greebo: This inserts a child node at the front of the list,
+ * saves the Undo state and notifies the owning node.
+ */
+ void prepend(const INodePtr& node);
/**
* greebo: This removes the node from the local set, saves the UndoMemento and notifies the owning node.
diff --git a/libs/scenelib.h b/libs/scenelib.h
index 5f854f3..f10fe18 100644
--- a/libs/scenelib.h
+++ b/libs/scenelib.h
@@ -162,8 +162,9 @@ public:
node->disable(Node::eLayered);
}
- if (!node->visible()) {
- // Node is hidden after update (and no children are visible), de-select
+ if (node->checkStateFlag(Node::eLayered))
+ {
+ // Node is hidden by layers after update (and no children are visible), de-select
Node_setSelected(node, false);
}
diff --git a/libs/wxutil/GLWidget.cpp b/libs/wxutil/GLWidget.cpp
index baad6c7..dcb5155 100644
--- a/libs/wxutil/GLWidget.cpp
+++ b/libs/wxutil/GLWidget.cpp
@@ -11,11 +11,12 @@ namespace wxutil
const int ATTRIBS [] = {
WX_GL_RGBA,
WX_GL_DOUBLEBUFFER,
- WX_GL_DEPTH_SIZE, 16
+ WX_GL_DEPTH_SIZE, 16,
+ 0
};
GLWidget::GLWidget(wxWindow *parent, const std::function<void()>& renderCallback, const std::string& name) :
- wxGLCanvas(parent, -1, ATTRIBS, wxDefaultPosition, wxDefaultSize,
+ wxGLCanvas(parent, wxID_ANY, ATTRIBS, wxDefaultPosition, wxDefaultSize,
wxFULL_REPAINT_ON_RESIZE | wxWANTS_CHARS,
wxString(name.c_str(), *wxConvCurrent)),
_registered(false),
diff --git a/libs/wxutil/Makefile.am b/libs/wxutil/Makefile.am
index 0de7507..83719e1 100644
--- a/libs/wxutil/Makefile.am
+++ b/libs/wxutil/Makefile.am
@@ -14,6 +14,8 @@ libwxutil_la_LDFLAGS = -release @PACKAGE_VERSION@ \
$(LIBSIGC_LIBS) \
$(WX_LIBS) \
$(GL_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(GLU_LIBS) \
$(FTGL_LIBS)
libwxutil_la_LIBADD = $(top_builddir)/libs/xmlutil/libxmlutil.la \
diff --git a/libs/wxutil/Makefile.in b/libs/wxutil/Makefile.in
index f6ec834..57155db 100644
--- a/libs/wxutil/Makefile.in
+++ b/libs/wxutil/Makefile.in
@@ -424,6 +424,8 @@ libwxutil_la_LDFLAGS = -release @PACKAGE_VERSION@ \
$(LIBSIGC_LIBS) \
$(WX_LIBS) \
$(GL_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(GLU_LIBS) \
$(FTGL_LIBS)
diff --git a/libs/wxutil/TreeModel.cpp b/libs/wxutil/TreeModel.cpp
index f3616ca..56aeca7 100644
--- a/libs/wxutil/TreeModel.cpp
+++ b/libs/wxutil/TreeModel.cpp
@@ -13,14 +13,9 @@ wxString TreeModel::Column::getWxType() const
if (types.empty())
{
types[String] = "string";
-#ifdef __WXGTK__
- // For wxGTK we store numbers as strings
+ // we store numbers as strings
types[Integer] = "string";
types[Double] = "string";
-#else
- types[Integer] = "long";
- types[Double] = "double";
-#endif
types[Boolean] = "bool";
types[Icon] = "icon";
types[IconText] = "wxDataViewIconText";
@@ -50,6 +45,9 @@ public:
typedef std::vector<wxDataViewItemAttr> Attributes;
Attributes attributes;
+ typedef std::vector<bool> EnabledFlags; // Each value can be flagged as enabled/disabled
+ EnabledFlags enabledFlags;
+
// Public constructor, does not accept NULL pointers
Node(Node* parent_) :
parent(parent_),
@@ -926,4 +924,34 @@ wxDataViewItem TreeModel::FindPrevString(const wxString& needle,
return functor.getMatch();
}
+bool TreeModel::IsEnabled(const wxDataViewItem& item, unsigned int col) const
+{
+ Node* owningNode = item.IsOk() ? static_cast<Node*>(item.GetID()) : _rootNode.get();
+
+ if (col < owningNode->enabledFlags.size())
+ {
+ return owningNode->enabledFlags[col];
+ }
+
+ // Column values without flags render as enabled by default
+ return true;
+}
+
+void TreeModel::SetEnabled(const wxDataViewItem& item, unsigned int col, bool enabled)
+{
+ if (!item.IsOk())
+ {
+ return;
+ }
+
+ Node* owningNode = static_cast<Node*>(item.GetID());
+
+ if (owningNode->enabledFlags.size() < col + 1)
+ {
+ owningNode->enabledFlags.resize(col + 1, true); // fill with true by default
+ }
+
+ owningNode->enabledFlags[col] = enabled;
+}
+
} // namespace
diff --git a/libs/wxutil/TreeModel.h b/libs/wxutil/TreeModel.h
index d119a6e..be53dcc 100644
--- a/libs/wxutil/TreeModel.h
+++ b/libs/wxutil/TreeModel.h
@@ -161,8 +161,7 @@ public:
// get/set operators
ItemValueProxy& operator=(const wxVariant& data)
{
-#ifdef __WXGTK__
- // wxGTK doesn't like rendering number columns directly (even though it works)
+ // wxGTK and wxWidgets 3.1.0+ doesn't like rendering number values as text
// so let's store numbers as strings automatically
if ((_column.type == Column::Integer || _column.type == Column::Double) &&
data.GetType() != "string")
@@ -174,9 +173,10 @@ public:
{
_model.SetValue(data, _item, _column.getColumnIndex());
}
-#else
- _model.SetValue(data, _item, _column.getColumnIndex());
-#endif
+
+ // Newly assigned values are enabled by default
+ _model.SetEnabled(_item, _column.getColumnIndex(), true);
+
return *this;
}
@@ -237,6 +237,18 @@ public:
return variant.IsNull() ? "" : variant.GetString().ToStdString();
}
+
+ bool isEnabled()
+ {
+ return _model.IsEnabled(_item, _column.getColumnIndex());
+ }
+
+ // Enable/disable the column value, by default values are enabled after assignment
+ // This is adhered by some cell renderers which draw the value greyed out or inactive
+ void setEnabled(bool enabled)
+ {
+ _model.SetEnabled(_item, _column.getColumnIndex(), enabled);
+ }
};
/**
@@ -376,6 +388,9 @@ public:
// Returns a Row reference to the topmost element
virtual Row GetRootItem();
+ // Returns true if the given column value should render as "enabled" or not
+ virtual bool IsEnabled(const wxDataViewItem& item, unsigned int col) const override;
+
// Removes all items - internally the root node will be kept, but cleared too
// This also fires the "Cleared" event to any listeners
virtual void Clear();
@@ -415,6 +430,9 @@ public:
virtual wxDataViewItem FindPrevString(const wxString& needle,
const std::vector<Column>& columns, const wxDataViewItem& previousMatch = wxDataViewItem());
+ // Marks a specific column value as enabled or disabled.
+ virtual void SetEnabled(const wxDataViewItem& item, unsigned int col, bool enabled);
+
// Base class implementation / overrides
virtual bool HasDefaultCompare() const;
diff --git a/libs/wxutil/TreeView.cpp b/libs/wxutil/TreeView.cpp
index 42a8c92..d41344c 100644
--- a/libs/wxutil/TreeView.cpp
+++ b/libs/wxutil/TreeView.cpp
@@ -21,6 +21,7 @@ TreeView::TreeView(wxWindow* parent, TreeModel::Ptr model, long style) :
Connect(wxEVT_CHAR, wxKeyEventHandler(TreeView::_onChar), NULL, this);
Connect(EV_TREEVIEW_SEARCH_EVENT, SearchEventHandler(TreeView::_onSearch), NULL, this);
+ Connect(wxEVT_DATAVIEW_ITEM_ACTIVATED, wxDataViewEventHandler(TreeView::_onItemActivated), NULL, this);
}
TreeView* TreeView::Create(wxWindow* parent, long style)
@@ -121,6 +122,18 @@ void TreeView::_onItemExpanded(wxDataViewEvent& ev)
ev.Skip();
}
+void TreeView::_onItemActivated(wxDataViewEvent& ev)
+{
+ if (!IsExpanded(ev.GetItem()))
+ {
+ Expand(ev.GetItem());
+ }
+ else
+ {
+ Collapse(ev.GetItem());
+ }
+}
+
wxDEFINE_EVENT(EV_TREEVIEW_SEARCH_EVENT, TreeView::SearchEvent);
TreeView::SearchEvent::SearchEvent(int id) :
diff --git a/libs/wxutil/TreeView.h b/libs/wxutil/TreeView.h
index 58fd194..4b22dc5 100644
--- a/libs/wxutil/TreeView.h
+++ b/libs/wxutil/TreeView.h
@@ -94,6 +94,7 @@ private:
void _onItemExpanded(wxDataViewEvent& ev);
void _onChar(wxKeyEvent& ev);
void _onSearch(SearchEvent& ev);
+ void _onItemActivated(wxDataViewEvent& ev);
};
// wx event macros
diff --git a/missing b/missing
index 1c8ff70..f62bbae 100755
--- a/missing
+++ b/missing
@@ -1,11 +1,10 @@
#! /bin/sh
-# Common stub for a few missing GNU programs while installing.
+# Common wrapper for a few potentially missing GNU programs.
-scriptversion=2006-05-10.23
+scriptversion=2013-10-28.13; # UTC
-# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
-# Free Software Foundation, Inc.
-# Originally by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard at iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,9 +17,7 @@ scriptversion=2006-05-10.23
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -28,66 +25,40 @@ scriptversion=2006-05-10.23
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
- echo 1>&2 "Try \`$0 --help' for more information"
+ echo 1>&2 "Try '$0 --help' for more information"
exit 1
fi
-run=:
-sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
-sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
-
-# In the cases where this matters, `missing' is being run in the
-# srcdir already.
-if test -f configure.ac; then
- configure_ac=configure.ac
-else
- configure_ac=configure.in
-fi
+case $1 in
-msg="missing on your system"
+ --is-lightweight)
+ # Used by our autoconf macros to check whether the available missing
+ # script is modern enough.
+ exit 0
+ ;;
-case $1 in
---run)
- # Try to run requested program, and just exit if it succeeds.
- run=
- shift
- "$@" && exit 0
- # Exit code 63 means version mismatch. This often happens
- # when the user try to use an ancient version of a tool on
- # a file that requires a minimum version. In this case we
- # we should proceed has if the program had been absent, or
- # if --run hadn't been passed.
- if test $? = 63; then
- run=:
- msg="probably too old"
- fi
- ;;
+ --run)
+ # Back-compat with the calling convention used by older automake.
+ shift
+ ;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
-Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
-error status if there is no known handling for PROGRAM.
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
- --run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
- aclocal touch file \`aclocal.m4'
- autoconf touch file \`configure'
- autoheader touch file \`config.h.in'
- autom4te touch the output file, or create a stub one
- automake touch all \`Makefile.in' files
- bison create \`y.tab.[ch]', if possible, from existing .[ch]
- flex create \`lex.yy.c', if possible, from existing .c
- help2man touch the output file
- lex create \`lex.yy.c', if possible, from existing .c
- makeinfo touch the output file
- tar try tar, gnutar, gtar, then tar without non-portable flags
- yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+ aclocal autoconf autoheader autom4te automake makeinfo
+ bison yacc flex lex help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
Send bug reports to <bug-automake at gnu.org>."
exit $?
@@ -99,269 +70,146 @@ Send bug reports to <bug-automake at gnu.org>."
;;
-*)
- echo 1>&2 "$0: Unknown \`$1' option"
- echo 1>&2 "Try \`$0 --help' for more information"
+ echo 1>&2 "$0: unknown '$1' option"
+ echo 1>&2 "Try '$0 --help' for more information"
exit 1
;;
esac
-# Now exit if we have it, but it failed. Also exit now if we
-# don't have it and --version was passed (most likely to detect
-# the program).
-case $1 in
- lex|yacc)
- # Not GNU programs, they don't have --version.
- ;;
-
- tar)
- if test -n "$run"; then
- echo 1>&2 "ERROR: \`tar' requires --run"
- exit 1
- elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
- exit 1
- fi
- ;;
-
- *)
- if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
- # We have it, but it failed.
- exit 1
- elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
- # Could not run --version or --help. This is probably someone
- # running `$TOOL --version' or `$TOOL --help' to check whether
- # $TOOL exists and not knowing $TOOL uses missing.
- exit 1
- fi
- ;;
-esac
-
-# If it does not exist, or fails to run (possibly an outdated version),
-# try to emulate it.
-case $1 in
- aclocal*)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`acinclude.m4' or \`${configure_ac}'. You might want
- to install the \`Automake' and \`Perl' packages. Grab them from
- any GNU archive site."
- touch aclocal.m4
- ;;
-
- autoconf)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`${configure_ac}'. You might want to install the
- \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
- archive site."
- touch configure
- ;;
-
- autoheader)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`acconfig.h' or \`${configure_ac}'. You might want
- to install the \`Autoconf' and \`GNU m4' packages. Grab them
- from any GNU archive site."
- files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
- test -z "$files" && files="config.h"
- touch_files=
- for f in $files; do
- case $f in
- *:*) touch_files="$touch_files "`echo "$f" |
- sed -e 's/^[^:]*://' -e 's/:.*//'`;;
- *) touch_files="$touch_files $f.in";;
- esac
- done
- touch $touch_files
- ;;
-
- automake*)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
- You might want to install the \`Automake' and \`Perl' packages.
- Grab them from any GNU archive site."
- find . -type f -name Makefile.am -print |
- sed 's/\.am$/.in/' |
- while read f; do touch "$f"; done
- ;;
-
- autom4te)
- echo 1>&2 "\
-WARNING: \`$1' is needed, but is $msg.
- You might have modified some files without having the
- proper tools for further handling them.
- You can get \`$1' as part of \`Autoconf' from any GNU
- archive site."
-
- file=`echo "$*" | sed -n "$sed_output"`
- test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
- if test -f "$file"; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo "#! /bin/sh"
- echo "# Created by GNU Automake missing as a replacement of"
- echo "# $ $@"
- echo "exit 0"
- chmod +x $file
- exit 1
- fi
- ;;
-
- bison|yacc)
- echo 1>&2 "\
-WARNING: \`$1' $msg. You should only need it if
- you modified a \`.y' file. You may need the \`Bison' package
- in order for those modifications to take effect. You can get
- \`Bison' from any GNU archive site."
- rm -f y.tab.c y.tab.h
- if test $# -ne 1; then
- eval LASTARG="\${$#}"
- case $LASTARG in
- *.y)
- SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
- if test -f "$SRCFILE"; then
- cp "$SRCFILE" y.tab.c
- fi
- SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
- if test -f "$SRCFILE"; then
- cp "$SRCFILE" y.tab.h
- fi
- ;;
- esac
- fi
- if test ! -f y.tab.h; then
- echo >y.tab.h
- fi
- if test ! -f y.tab.c; then
- echo 'main() { return 0; }' >y.tab.c
- fi
- ;;
-
- lex|flex)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a \`.l' file. You may need the \`Flex' package
- in order for those modifications to take effect. You can get
- \`Flex' from any GNU archive site."
- rm -f lex.yy.c
- if test $# -ne 1; then
- eval LASTARG="\${$#}"
- case $LASTARG in
- *.l)
- SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
- if test -f "$SRCFILE"; then
- cp "$SRCFILE" lex.yy.c
- fi
- ;;
- esac
- fi
- if test ! -f lex.yy.c; then
- echo 'main() { return 0; }' >lex.yy.c
- fi
- ;;
-
- help2man)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a dependency of a manual page. You may need the
- \`Help2man' package in order for those modifications to take
- effect. You can get \`Help2man' from any GNU archive site."
-
- file=`echo "$*" | sed -n "$sed_output"`
- test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
- if test -f "$file"; then
- touch $file
- else
- test -z "$file" || exec >$file
- echo ".ab help2man is required to generate this page"
- exit 1
- fi
- ;;
-
- makeinfo)
- echo 1>&2 "\
-WARNING: \`$1' is $msg. You should only need it if
- you modified a \`.texi' or \`.texinfo' file, or any other file
- indirectly affecting the aspect of the manual. The spurious
- call might also be the consequence of using a buggy \`make' (AIX,
- DU, IRIX). You might want to install the \`Texinfo' package or
- the \`GNU make' package. Grab either from any GNU archive site."
- # The file to touch is that specified with -o ...
- file=`echo "$*" | sed -n "$sed_output"`
- test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
- if test -z "$file"; then
- # ... or it is the one specified with @setfilename ...
- infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
- file=`sed -n '
- /^@setfilename/{
- s/.* \([^ ]*\) *$/\1/
- p
- q
- }' $infile`
- # ... or it is derived from the source name (dir/f.texi becomes f.info)
- test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
- fi
- # If the file does not exist, the user really needs makeinfo;
- # let's fail without touching anything.
- test -f $file || exit 1
- touch $file
- ;;
-
- tar)
- shift
-
- # We have already tried tar in the generic part.
- # Look for gnutar/gtar before invocation to avoid ugly error
- # messages.
- if (gnutar --version > /dev/null 2>&1); then
- gnutar "$@" && exit 0
- fi
- if (gtar --version > /dev/null 2>&1); then
- gtar "$@" && exit 0
- fi
- firstarg="$1"
- if shift; then
- case $firstarg in
- *o*)
- firstarg=`echo "$firstarg" | sed s/o//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- case $firstarg in
- *h*)
- firstarg=`echo "$firstarg" | sed s/h//`
- tar "$firstarg" "$@" && exit 0
- ;;
- esac
- fi
-
- echo 1>&2 "\
-WARNING: I can't seem to be able to run \`tar' with the given arguments.
- You may want to install GNU tar or Free paxutils, or check the
- command line arguments."
- exit 1
- ;;
-
- *)
- echo 1>&2 "\
-WARNING: \`$1' is needed, and is $msg.
- You might have modified some files without having the
- proper tools for further handling them. Check the \`README' file,
- it often tells you about the needed prerequisites for installing
- this package. You may also peek at any GNU archive site, in case
- some other package would contain this missing \`$1' program."
- exit 1
- ;;
-esac
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch. This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+ msg="probably too old"
+elif test $st -eq 127; then
+ # Program was missing.
+ msg="missing on your system"
+else
+ # Program was found and executed, but failed. Give up.
+ exit $st
+fi
-exit 0
+perl_URL=http://www.perl.org/
+flex_URL=http://flex.sourceforge.net/
+gnu_software_URL=http://www.gnu.org/software
+
+program_details ()
+{
+ case $1 in
+ aclocal|automake)
+ echo "The '$1' program is part of the GNU Automake package:"
+ echo "<$gnu_software_URL/automake>"
+ echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/autoconf>"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ autoconf|autom4te|autoheader)
+ echo "The '$1' program is part of the GNU Autoconf package:"
+ echo "<$gnu_software_URL/autoconf/>"
+ echo "It also requires GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ esac
+}
+
+give_advice ()
+{
+ # Normalize program name to check for.
+ normalized_program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+ printf '%s\n' "'$1' is $msg."
+
+ configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+ case $normalized_program in
+ autoconf*)
+ echo "You should only need it if you modified 'configure.ac',"
+ echo "or m4 files included by it."
+ program_details 'autoconf'
+ ;;
+ autoheader*)
+ echo "You should only need it if you modified 'acconfig.h' or"
+ echo "$configure_deps."
+ program_details 'autoheader'
+ ;;
+ automake*)
+ echo "You should only need it if you modified 'Makefile.am' or"
+ echo "$configure_deps."
+ program_details 'automake'
+ ;;
+ aclocal*)
+ echo "You should only need it if you modified 'acinclude.m4' or"
+ echo "$configure_deps."
+ program_details 'aclocal'
+ ;;
+ autom4te*)
+ echo "You might have modified some maintainer files that require"
+ echo "the 'autom4te' program to be rebuilt."
+ program_details 'autom4te'
+ ;;
+ bison*|yacc*)
+ echo "You should only need it if you modified a '.y' file."
+ echo "You may want to install the GNU Bison package:"
+ echo "<$gnu_software_URL/bison/>"
+ ;;
+ lex*|flex*)
+ echo "You should only need it if you modified a '.l' file."
+ echo "You may want to install the Fast Lexical Analyzer package:"
+ echo "<$flex_URL>"
+ ;;
+ help2man*)
+ echo "You should only need it if you modified a dependency" \
+ "of a man page."
+ echo "You may want to install the GNU Help2man package:"
+ echo "<$gnu_software_URL/help2man/>"
+ ;;
+ makeinfo*)
+ echo "You should only need it if you modified a '.texi' file, or"
+ echo "any other file indirectly affecting the aspect of the manual."
+ echo "You might want to install the Texinfo package:"
+ echo "<$gnu_software_URL/texinfo/>"
+ echo "The spurious makeinfo call might also be the consequence of"
+ echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+ echo "want to install GNU make:"
+ echo "<$gnu_software_URL/make/>"
+ ;;
+ *)
+ echo "You might have modified some files without having the proper"
+ echo "tools for further handling them. Check the 'README' file, it"
+ echo "often tells you about the needed prerequisites for installing"
+ echo "this package. You may also peek at any GNU archive site, in"
+ echo "case some other package contains this missing '$1' program."
+ ;;
+ esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+ -e '2,$s/^/ /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
# End:
diff --git a/plugins/dm.conversation/ConversationDialog.cpp b/plugins/dm.conversation/ConversationDialog.cpp
index 64ec440..a1f3000 100644
--- a/plugins/dm.conversation/ConversationDialog.cpp
+++ b/plugins/dm.conversation/ConversationDialog.cpp
@@ -46,7 +46,7 @@ ConversationDialog::ConversationDialog() :
void ConversationDialog::populateWindow()
{
- wxPanel* mainPanel = loadNamedPanel(this, "ConvDialogMainPanel");
+ loadNamedPanel(this, "ConvDialogMainPanel");
wxPanel* entityPanel = findNamedObject<wxPanel>(this, "ConvDialogEntityPanel");
@@ -148,6 +148,8 @@ void ConversationDialog::refreshConversationList()
// If there is at least one conversation, make the Clear button available
_clearConvButton->Enable(!_curEntity->second->isEmpty());
+
+ handleConversationSelectionChange();
}
void ConversationDialog::populateWidgets()
@@ -306,6 +308,11 @@ void ConversationDialog::onDeleteEntity(wxCommandEvent& ev)
// Callback for current conversation selection changed
void ConversationDialog::onConversationSelectionChanged(wxDataViewEvent& ev)
{
+ handleConversationSelectionChange();
+}
+
+void ConversationDialog::handleConversationSelectionChange()
+{
// Get the selection
_currentConversation = _convView->GetSelection();
diff --git a/plugins/dm.conversation/ConversationDialog.h b/plugins/dm.conversation/ConversationDialog.h
index 04d0dad..bd986fb 100644
--- a/plugins/dm.conversation/ConversationDialog.h
+++ b/plugins/dm.conversation/ConversationDialog.h
@@ -73,6 +73,7 @@ private:
// Re-loads the conversation from the selected entity
void refreshConversationList();
void updateConversationPanelSensitivity();
+ void handleConversationSelectionChange();
// WIDGET POPULATION
void populateWindow();
diff --git a/plugins/dm.conversation/ConversationEditor.cpp b/plugins/dm.conversation/ConversationEditor.cpp
index 65c8641..7407363 100644
--- a/plugins/dm.conversation/ConversationEditor.cpp
+++ b/plugins/dm.conversation/ConversationEditor.cpp
@@ -52,9 +52,31 @@ void ConversationEditor::populateWindow()
makeLabelBold(this, "ConvEditorActorLabel");
makeLabelBold(this, "ConvEditorCommandLabel");
+ findNamedObject<wxTextCtrl>(this, "ConvEditorNameEntry")->Bind(wxEVT_TEXT, [&](wxCommandEvent& ev)
+ {
+ if (!_updateInProgress)
+ {
+ _conversation.name = ev.GetString();
+ }
+ });
+
findNamedObject<wxCheckBox>(this, "ConvEditorRepeatCheckbox")->Connect(
wxEVT_CHECKBOX, wxCommandEventHandler(ConversationEditor::onMaxPlayCountEnabled), NULL, this);
+ findNamedObject<wxCheckBox>(this, "ConvEditorActorsWithinTalkDistance")->Bind(wxEVT_CHECKBOX,
+ [&](wxCommandEvent& ev) { _conversation.actorsMustBeWithinTalkdistance = ev.IsChecked(); });
+ findNamedObject<wxCheckBox>(this, "ConvEditorActorsMustFace")->Bind(wxEVT_CHECKBOX,
+ [&](wxCommandEvent& ev) { _conversation.actorsAlwaysFaceEachOther = ev.IsChecked(); });
+
+ findNamedObject<wxSpinCtrl>(this, "ConvEditorRepeatTimes")->Bind(wxEVT_SPINCTRL, [&](wxSpinEvent& ev)
+ {
+ if (!_updateInProgress)
+ {
+ _conversation.maxPlayCount = ev.GetValue();
+ updateWidgets();
+ }
+ });
+
// Actor Panel
wxPanel* actorPanel = findNamedObject<wxPanel>(this, "ConvEditorActorPanel");
@@ -350,6 +372,9 @@ void ConversationEditor::onMaxPlayCountEnabled(wxCommandEvent& ev)
findNamedObject<wxSpinCtrl>(this, "ConvEditorRepeatTimes")->Enable(false);
findNamedObject<wxStaticText>(this, "ConvEditorRepeatAdditionalText")->Enable(false);
}
+
+ // Update the value in the conversation as well
+ _conversation.maxPlayCount = findNamedObject<wxSpinCtrl>(this, "ConvEditorRepeatTimes")->GetValue();
}
void ConversationEditor::onAddActor(wxCommandEvent& ev)
diff --git a/plugins/dm.editing/AIEditingPanel.cpp b/plugins/dm.editing/AIEditingPanel.cpp
index 1663055..e7b5c93 100644
--- a/plugins/dm.editing/AIEditingPanel.cpp
+++ b/plugins/dm.editing/AIEditingPanel.cpp
@@ -94,7 +94,7 @@ void AIEditingPanel::constructWidgets()
_spinButtons["min_interleave_think_dist"] = new SpawnargLinkedSpinButton(_mainPanel, _("Min. Interleave Distance"), "min_interleave_think_dist", 0, 60000, 50, 0);
_spinButtons["max_interleave_think_dist"] = new SpawnargLinkedSpinButton(_mainPanel, _("Max. Interleave Distance"), "max_interleave_think_dist", 0, 60000, 50, 0);
- _spinButtons["health"] = new SpawnargLinkedSpinButton(_mainPanel, _("Health"), "health", 0, 1000, 5, 0);
+ _spinButtons["health"] = new SpawnargLinkedSpinButton(_mainPanel, _("Health"), "health", 0, 9999999, 5, 0);
_spinButtons["health_critical"] = new SpawnargLinkedSpinButton(_mainPanel, _("Critical Health"), "health_critical", 0, 1000, 5, 0);
_spinButtons["melee_range"] = new SpawnargLinkedSpinButton(_mainPanel, _("Melee Range"), "melee_range", 0, 200, 1, 0);
@@ -207,7 +207,7 @@ wxSizer* AIEditingPanel::createSpinButtonHbox(SpawnargLinkedSpinButton* spinButt
wxStaticText* label = new wxStaticText(spinButton->GetParent(), wxID_ANY, spinButton->getLabel() + ":");
hbox->Add(label, 1, wxALIGN_CENTER_VERTICAL | wxRIGHT, 6);
- hbox->Add(spinButton, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
+ hbox->Add(spinButton, 0, wxALIGN_CENTER_VERTICAL);
return hbox;
}
@@ -267,9 +267,9 @@ void AIEditingPanel::onRadiantStartup()
page->page = Instance()._mainPanel;
page->tabIcon = "icon_ai.png";
page->tabLabel = _("AI");
- page->insertBefore = "mediabrowser";
+ page->position = IGroupDialog::Page::Position::MediaBrowser - 10;
- // Add the Media Browser page
+ // Add the page
GlobalGroupDialog().addPage(page);
// Delete the temporary parent
@@ -383,7 +383,7 @@ void AIEditingPanel::rescanSelection()
updateWidgetsFromSelection();
}
-void AIEditingPanel::onSelectionChanged(const Selectable& selectable)
+void AIEditingPanel::onSelectionChanged(const ISelectable& selectable)
{
// Immediately disconnect from the current entity in any case
if (_entity != nullptr)
diff --git a/plugins/dm.editing/AIEditingPanel.h b/plugins/dm.editing/AIEditingPanel.h
index 3e2ba6c..29067e6 100644
--- a/plugins/dm.editing/AIEditingPanel.h
+++ b/plugins/dm.editing/AIEditingPanel.h
@@ -8,7 +8,7 @@
#include <sigc++/connection.h>
#include <wx/event.h>
-class Selectable;
+class ISelectable;
class Entity;
class wxStaticText;
class wxScrolledWindow;
@@ -78,7 +78,7 @@ private:
const std::string& key);
void onRadiantShutdown();
- void onSelectionChanged(const Selectable& selectable);
+ void onSelectionChanged(const ISelectable& selectable);
void rescanSelection();
diff --git a/plugins/dm.editing/AIHeadPropertyEditor.cpp b/plugins/dm.editing/AIHeadPropertyEditor.cpp
index a8fb5bc..4495f24 100644
--- a/plugins/dm.editing/AIHeadPropertyEditor.cpp
+++ b/plugins/dm.editing/AIHeadPropertyEditor.cpp
@@ -48,6 +48,11 @@ wxPanel* AIHeadPropertyEditor::getWidget()
return _widget;
}
+void AIHeadPropertyEditor::updateFromEntity()
+{
+ // nothing to do
+}
+
IPropertyEditorPtr AIHeadPropertyEditor::createNew(wxWindow* parent, Entity* entity,
const std::string& key, const std::string& options)
{
diff --git a/plugins/dm.editing/AIHeadPropertyEditor.h b/plugins/dm.editing/AIHeadPropertyEditor.h
index 89a5815..1ab7f9f 100644
--- a/plugins/dm.editing/AIHeadPropertyEditor.h
+++ b/plugins/dm.editing/AIHeadPropertyEditor.h
@@ -28,14 +28,15 @@ public:
~AIHeadPropertyEditor();
- wxPanel* getWidget();
+ wxPanel* getWidget() override;
+ void updateFromEntity() override;
AIHeadPropertyEditor(wxWindow* parent, Entity* entity,
const std::string& key, const std::string& options);
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& key,
- const std::string& options);
+ const std::string& options) override;
std::string runDialog(Entity* entity, const std::string& key);
diff --git a/plugins/dm.editing/AIVocalSetPropertyEditor.cpp b/plugins/dm.editing/AIVocalSetPropertyEditor.cpp
index b83dd2a..463100a 100644
--- a/plugins/dm.editing/AIVocalSetPropertyEditor.cpp
+++ b/plugins/dm.editing/AIVocalSetPropertyEditor.cpp
@@ -48,6 +48,11 @@ wxPanel* AIVocalSetPropertyEditor::getWidget()
return _widget;
}
+void AIVocalSetPropertyEditor::updateFromEntity()
+{
+ // Nothing to do
+}
+
IPropertyEditorPtr AIVocalSetPropertyEditor::createNew(wxWindow* parent, Entity* entity,
const std::string& key, const std::string& options)
{
diff --git a/plugins/dm.editing/AIVocalSetPropertyEditor.h b/plugins/dm.editing/AIVocalSetPropertyEditor.h
index 0657e5e..f91a56c 100644
--- a/plugins/dm.editing/AIVocalSetPropertyEditor.h
+++ b/plugins/dm.editing/AIVocalSetPropertyEditor.h
@@ -31,11 +31,12 @@ public:
AIVocalSetPropertyEditor(wxWindow* parent, Entity* entity,
const std::string& key, const std::string& options);
- wxPanel* getWidget();
+ wxPanel* getWidget() override;
+ void updateFromEntity() override;
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& key,
- const std::string& options);
+ const std::string& options) override;
std::string runDialog(Entity* entity, const std::string& key);
diff --git a/plugins/dm.editing/Makefile.am b/plugins/dm.editing/Makefile.am
index ba57af2..6cec7bb 100644
--- a/plugins/dm.editing/Makefile.am
+++ b/plugins/dm.editing/Makefile.am
@@ -7,7 +7,11 @@ plugins_LTLIBRARIES = dm_editing.la
dm_editing_la_LIBADD = $(top_builddir)/libs/wxutil/libwxutil.la \
$(top_builddir)/libs/xmlutil/libxmlutil.la
dm_editing_la_LDFLAGS = -module -avoid-version \
- $(WX_LIBS) $(XML_LIBS) $(BOOST_REGEX_LIBS)
+ $(WX_LIBS) \
+ $(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(BOOST_REGEX_LIBS)
dm_editing_la_SOURCES = plugin.cpp \
AIHeadPropertyEditor.cpp \
AIEditingPanel.cpp \
diff --git a/plugins/dm.editing/Makefile.in b/plugins/dm.editing/Makefile.in
index b57d3c2..d89b992 100644
--- a/plugins/dm.editing/Makefile.in
+++ b/plugins/dm.editing/Makefile.in
@@ -410,7 +410,11 @@ dm_editing_la_LIBADD = $(top_builddir)/libs/wxutil/libwxutil.la \
$(top_builddir)/libs/xmlutil/libxmlutil.la
dm_editing_la_LDFLAGS = -module -avoid-version \
- $(WX_LIBS) $(XML_LIBS) $(BOOST_REGEX_LIBS)
+ $(WX_LIBS) \
+ $(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(BOOST_REGEX_LIBS)
dm_editing_la_SOURCES = plugin.cpp \
AIHeadPropertyEditor.cpp \
diff --git a/plugins/dm.gui/plugin.cpp b/plugins/dm.gui/plugin.cpp
index bb4c1d1..e40e7d3 100644
--- a/plugins/dm.gui/plugin.cpp
+++ b/plugins/dm.gui/plugin.cpp
@@ -107,7 +107,7 @@ public:
void constructPreferences()
{
// Add a page to the given group
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Readable Editor"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Readable Editor"));
ComboBoxValueList options;
@@ -115,9 +115,9 @@ public:
options.push_back(_("Mod Base/xdata"));
options.push_back(_("Custom Folder"));
- page->appendCombo(_("XData Storage Folder"), ui::RKEY_READABLES_STORAGE_FOLDER, options);
+ page.appendCombo(_("XData Storage Folder"), ui::RKEY_READABLES_STORAGE_FOLDER, options);
- page->appendPathEntry(_("Custom Folder"), ui::RKEY_READABLES_CUSTOM_FOLDER, true);
+ page.appendPathEntry(_("Custom Folder"), ui::RKEY_READABLES_CUSTOM_FOLDER, true);
}
void shutdownModule()
diff --git a/plugins/dm.objectives/ObjectiveEntityFinder.cpp b/plugins/dm.objectives/ObjectiveEntityFinder.cpp
index 5d124df..db20580 100644
--- a/plugins/dm.objectives/ObjectiveEntityFinder.cpp
+++ b/plugins/dm.objectives/ObjectiveEntityFinder.cpp
@@ -14,7 +14,7 @@ bool ObjectiveEntityFinder::pre(const scene::INodePtr& node)
// We have an entity at this point
- if (ePtr->getKeyValue("classname") == "worldspawn")
+ if (ePtr->isWorldspawn())
{
_worldSpawn = ePtr;
return false; // Don't traverse worldspawn children
diff --git a/plugins/dm.stimresponse/EffectEditor.cpp b/plugins/dm.stimresponse/EffectEditor.cpp
index 340dbf0..15b3b25 100644
--- a/plugins/dm.stimresponse/EffectEditor.cpp
+++ b/plugins/dm.stimresponse/EffectEditor.cpp
@@ -167,7 +167,7 @@ void EffectEditor::createArgumentWidgets(ResponseEffect& effect)
for (ResponseEffect::ArgumentList::iterator i = list.begin();
i != list.end(); ++i)
{
- int index = i->first;
+ //int index = i->first;
ResponseEffect::Argument& arg = i->second;
ArgumentItemPtr item;
diff --git a/plugins/entity/Doom3Entity.cpp b/plugins/entity/Doom3Entity.cpp
index 5120f25..304365a 100644
--- a/plugins/entity/Doom3Entity.cpp
+++ b/plugins/entity/Doom3Entity.cpp
@@ -211,6 +211,11 @@ EntityKeyValuePtr Doom3Entity::getEntityKeyValue(const std::string& key)
return (found != _keyValues.end()) ? found->second : EntityKeyValuePtr();
}
+bool Doom3Entity::isWorldspawn() const
+{
+ return getKeyValue("classname") == "worldspawn";
+}
+
bool Doom3Entity::isContainer() const
{
return _isContainer;
diff --git a/plugins/entity/Doom3Entity.h b/plugins/entity/Doom3Entity.h
index 84b29a0..79046c2 100644
--- a/plugins/entity/Doom3Entity.h
+++ b/plugins/entity/Doom3Entity.h
@@ -54,44 +54,45 @@ public:
void importState(const KeyValues& keyValues);
/* Entity implementation */
- void attachObserver(Observer* observer);
- void detachObserver(Observer* observer);
+ void attachObserver(Observer* observer) override;
+ void detachObserver(Observer* observer) override;
void connectUndoSystem(IMapFileChangeTracker& changeTracker);
void disconnectUndoSystem(IMapFileChangeTracker& changeTracker);
/** Return the EntityClass associated with this entity.
*/
- IEntityClassPtr getEntityClass() const;
+ IEntityClassPtr getEntityClass() const override;
- void forEachKeyValue(const KeyValueVisitFunctor& func) const;
- void forEachEntityKeyValue(const EntityKeyValueVisitFunctor& visitor);
+ void forEachKeyValue(const KeyValueVisitFunctor& func) const override;
+ void forEachEntityKeyValue(const EntityKeyValueVisitFunctor& visitor) override;
/** Set a keyvalue on the entity.
*/
- void setKeyValue(const std::string& key, const std::string& value);
+ void setKeyValue(const std::string& key, const std::string& value) override;
/** Retrieve a keyvalue from the entity.
*/
- std::string getKeyValue(const std::string& key) const;
+ std::string getKeyValue(const std::string& key) const override;
// Returns true if the given key is inherited
- bool isInherited(const std::string& key) const;
+ bool isInherited(const std::string& key) const override;
// Get all KeyValues matching the given prefix.
- KeyValuePairs getKeyValuePairs(const std::string& prefix) const;
+ KeyValuePairs getKeyValuePairs(const std::string& prefix) const override;
- bool isContainer() const;
+ bool isWorldspawn() const override;
+ bool isContainer() const override;
void setIsContainer(bool isContainer);
- bool isModel() const;
+ bool isModel() const override;
// Returns the actual pointer to a KeyValue (or NULL if not found),
// not just the string like getKeyValue() does.
// Only returns non-NULL for non-inherited keyvalues.
EntityKeyValuePtr getEntityKeyValue(const std::string& key);
- bool isOfType(const std::string& className);
+ bool isOfType(const std::string& className) override;
private:
diff --git a/plugins/entity/EntityNode.cpp b/plugins/entity/EntityNode.cpp
index 4456717..eb27d5a 100644
--- a/plugins/entity/EntityNode.cpp
+++ b/plugins/entity/EntityNode.cpp
@@ -252,9 +252,11 @@ void EntityNode::setRenderSystem(const RenderSystemPtr& renderSystem)
_colourKey.setRenderSystem(renderSystem);
}
-bool EntityNode::isHighlighted() const
+std::size_t EntityNode::getHighlightFlags()
{
- return isSelected();
+ if (!isSelected()) return Highlight::NoHighlight;
+
+ return isGroupMember() ? (Highlight::Selected | Highlight::GroupMember) : Highlight::Selected;
}
const Vector3& EntityNode::getColour() const
diff --git a/plugins/entity/EntityNode.h b/plugins/entity/EntityNode.h
index 193f5ad..716e34b 100644
--- a/plugins/entity/EntityNode.h
+++ b/plugins/entity/EntityNode.h
@@ -4,7 +4,7 @@
#include "inamespace.h"
#include "Bounded.h"
-#include "SelectableNode.h"
+#include "scene/SelectableNode.h"
#include "transformlib.h"
#include "NamespaceManager.h"
@@ -118,10 +118,10 @@ public:
Type getNodeType() const;
// Renderable implementation, can be overridden by subclasses
- virtual void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- virtual void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- virtual void setRenderSystem(const RenderSystemPtr& renderSystem);
- virtual bool isHighlighted() const;
+ virtual void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ virtual void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ virtual void setRenderSystem(const RenderSystemPtr& renderSystem) override;
+ virtual std::size_t getHighlightFlags() override;
// Adds/removes the keyobserver to/from the KeyObserverMap
void addKeyObserver(const std::string& key, KeyObserver& observer);
diff --git a/plugins/entity/VertexInstance.h b/plugins/entity/VertexInstance.h
index 2ca5c9d..8ef9255 100644
--- a/plugins/entity/VertexInstance.h
+++ b/plugins/entity/VertexInstance.h
@@ -10,7 +10,7 @@
class VertexInstance :
public OpenGLRenderable,
- public Selectable
+ public ISelectable
{
protected:
Vector3& _vertex;
@@ -87,8 +87,8 @@ public:
const VolumeTest& volume,
const Matrix4& localToWorld) const
{
- collector.highlightPrimitives(false);
- collector.highlightFaces(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, false);
collector.SetState(_shader, RenderableCollector::eFullMaterials);
collector.SetState(_shader, RenderableCollector::eWireframeOnly);
diff --git a/plugins/entity/curve/CurveEditInstance.cpp b/plugins/entity/curve/CurveEditInstance.cpp
index 631455c..e389169 100644
--- a/plugins/entity/curve/CurveEditInstance.cpp
+++ b/plugins/entity/curve/CurveEditInstance.cpp
@@ -56,6 +56,14 @@ bool CurveEditInstance::isSelected() const {
return false;
}
+void CurveEditInstance::invertSelected()
+{
+ for (selection::ObservedSelectable& i : _selectables)
+ {
+ i.setSelected(!i.isSelected());
+ }
+}
+
void CurveEditInstance::setSelected(bool selected) {
for(Selectables::iterator i = _selectables.begin(); i != _selectables.end(); ++i) {
i->setSelected(selected);
@@ -173,7 +181,7 @@ void CurveEditInstance::renderComponentsSelected(RenderableCollector& collector,
updateSelected();
if(!m_selectedRender.empty())
{
- collector.highlightPrimitives(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
collector.SetState(_shaders.selectedShader, RenderableCollector::eWireframeOnly);
collector.SetState(_shaders.selectedShader, RenderableCollector::eFullMaterials);
collector.addRenderable(m_selectedRender, localToWorld);
diff --git a/plugins/entity/curve/CurveEditInstance.h b/plugins/entity/curve/CurveEditInstance.h
index 50c57d9..9b70764 100644
--- a/plugins/entity/curve/CurveEditInstance.h
+++ b/plugins/entity/curve/CurveEditInstance.h
@@ -68,6 +68,7 @@ public:
bool isSelected() const;
void setSelected(bool selected);
+ void invertSelected();
unsigned int numSelected() const;
void write(const std::string& key, Entity& entity);
diff --git a/plugins/entity/doom3group/Doom3Group.cpp b/plugins/entity/doom3group/Doom3Group.cpp
index a60aa86..63dde03 100644
--- a/plugins/entity/doom3group/Doom3Group.cpp
+++ b/plugins/entity/doom3group/Doom3Group.cpp
@@ -320,17 +320,20 @@ void Doom3Group::setIsModel(bool newValue) {
/** Determine if this Doom3Group is a model (func_static) or a
* brush-containing entity. If the "model" key is equal to the
* "name" key, then this is a brush-based entity, otherwise it is
- * a model entity. The exception to this is for the "worldspawn"
+ * a model entity. The exception to this is the "worldspawn"
* entity class, which is always a brush-based entity.
*/
-void Doom3Group::updateIsModel() {
- if (m_modelKey != m_name && _entity.getKeyValue("classname") != "worldspawn") {
+void Doom3Group::updateIsModel()
+{
+ if (m_modelKey != m_name && !_entity.isWorldspawn())
+ {
setIsModel(true);
// Set the renderable name back to 0,0,0
_owner._renderableName.setOrigin(Vector3(0,0,0));
}
- else {
+ else
+ {
setIsModel(false);
// Update the renderable name
diff --git a/plugins/entity/doom3group/Doom3GroupNode.cpp b/plugins/entity/doom3group/Doom3GroupNode.cpp
index dfbaf62..9660015 100644
--- a/plugins/entity/doom3group/Doom3GroupNode.cpp
+++ b/plugins/entity/doom3group/Doom3GroupNode.cpp
@@ -152,7 +152,7 @@ void Doom3GroupNode::removeOriginFromChildren()
}
}
-void Doom3GroupNode::selectionChangedComponent(const Selectable& selectable) {
+void Doom3GroupNode::selectionChangedComponent(const ISelectable& selectable) {
GlobalSelectionSystem().onComponentSelection(Node::getSelf(), selectable);
}
@@ -168,6 +168,16 @@ void Doom3GroupNode::setSelectedComponents(bool selected, SelectionSystem::EComp
}
}
+void Doom3GroupNode::invertSelectedComponents(SelectionSystem::EComponentMode mode)
+{
+ if (mode == SelectionSystem::eVertex)
+ {
+ _nurbsEditInstance.invertSelected();
+ _catmullRomEditInstance.invertSelected();
+ _originInstance.invertSelected();
+ }
+}
+
void Doom3GroupNode::testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
{
if (mode == SelectionSystem::eVertex)
diff --git a/plugins/entity/doom3group/Doom3GroupNode.h b/plugins/entity/doom3group/Doom3GroupNode.h
index da698de..f0b9b67 100644
--- a/plugins/entity/doom3group/Doom3GroupNode.h
+++ b/plugins/entity/doom3group/Doom3GroupNode.h
@@ -66,9 +66,10 @@ public:
void testSelect(Selector& selector, SelectionTest& test);
// ComponentSelectionTestable implementation
- bool isSelectedComponents() const;
- void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode);
- void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode);
+ bool isSelectedComponents() const override;
+ void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode) override;
+ void invertSelectedComponents(SelectionSystem::EComponentMode mode) override;
+ void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) override;
// override scene::Inode::onRemoveFromScene to deselect the child components
virtual void onInsertIntoScene(scene::IMapRootNode& root) override;
@@ -83,7 +84,7 @@ public:
// Snappable implementation
virtual void snapto(float snap);
- void selectionChangedComponent(const Selectable& selectable);
+ void selectionChangedComponent(const ISelectable& selectable);
scene::INodePtr clone() const;
@@ -94,11 +95,11 @@ public:
void removeOriginFromChildren();
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const override;
void transformComponents(const Matrix4& matrix);
diff --git a/plugins/entity/eclassmodel/EclassModelNode.h b/plugins/entity/eclassmodel/EclassModelNode.h
index d4626ba..fd0ddcd 100644
--- a/plugins/entity/eclassmodel/EclassModelNode.h
+++ b/plugins/entity/eclassmodel/EclassModelNode.h
@@ -63,9 +63,9 @@ public:
scene::INodePtr clone() const;
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
// Returns the original "origin" value
const Vector3& getUntransformedOrigin() override;
diff --git a/plugins/entity/generic/GenericEntityNode.cpp b/plugins/entity/generic/GenericEntityNode.cpp
index 8603b42..d0317db 100644
--- a/plugins/entity/generic/GenericEntityNode.cpp
+++ b/plugins/entity/generic/GenericEntityNode.cpp
@@ -7,7 +7,6 @@ namespace entity {
GenericEntityNode::GenericEntityNode(const IEntityClassPtr& eclass) :
EntityNode(eclass),
m_contained(*this),
- _localPivot(Matrix4::getIdentity()),
_solidAABBRenderMode(SolidBoxes)
{}
@@ -15,7 +14,6 @@ GenericEntityNode::GenericEntityNode(const GenericEntityNode& other) :
EntityNode(other),
Snappable(other),
m_contained(other.m_contained, *this),
- _localPivot(other._localPivot),
_solidAABBRenderMode(other._solidAABBRenderMode)
{}
@@ -156,9 +154,4 @@ void GenericEntityNode::onChildRemoved(const scene::INodePtr& child)
});
}
-const Matrix4& GenericEntityNode::getLocalPivot() const
-{
- return _localPivot;
-}
-
} // namespace entity
diff --git a/plugins/entity/generic/GenericEntityNode.h b/plugins/entity/generic/GenericEntityNode.h
index c48c391..6bdbc9f 100644
--- a/plugins/entity/generic/GenericEntityNode.h
+++ b/plugins/entity/generic/GenericEntityNode.h
@@ -19,16 +19,12 @@ typedef std::shared_ptr<GenericEntityNode> GenericEntityNodePtr;
class GenericEntityNode :
public EntityNode,
- public Snappable,
- public Editable
+ public Snappable
{
friend class GenericEntity;
GenericEntity m_contained;
- // The local pivot of this generic node is always at the local origin 0,0,0
- Matrix4 _localPivot;
-
// Whether to draw a solid/shaded box in full material render mode or just the wireframe
enum SolidAAABBRenderMode
{
@@ -59,17 +55,14 @@ public:
scene::INodePtr clone() const;
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
SolidAAABBRenderMode getSolidAABBRenderMode() const;
// Override EntityNode::getDirection()
const Vector3& getDirection() const;
- // Editable - to prevent the selection system from including particle bounds in the pivot calculation
- const Matrix4& getLocalPivot() const;
-
// Returns the original "origin" value
const Vector3& getUntransformedOrigin() override;
diff --git a/plugins/entity/light/Light.cpp b/plugins/entity/light/Light.cpp
index cbca7ee..9668427 100644
--- a/plugins/entity/light/Light.cpp
+++ b/plugins/entity/light/Light.cpp
@@ -536,8 +536,8 @@ void Light::renderProjectionPoints(RenderableCollector& collector,
const Matrix4& localToWorld) const
{
// Add the renderable light target
- collector.highlightPrimitives(false);
- collector.highlightFaces(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, false);
collector.SetState(_rRight.getShader(), RenderableCollector::eFullMaterials);
collector.SetState(_rRight.getShader(), RenderableCollector::eWireframeOnly);
@@ -569,8 +569,8 @@ void Light::renderLightCentre(RenderableCollector& collector,
const VolumeTest& volume,
const Matrix4& localToWorld) const
{
- collector.highlightPrimitives(false);
- collector.highlightFaces(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, false);
collector.SetState(_rCentre.getShader(), RenderableCollector::eFullMaterials);
collector.SetState(_rCentre.getShader(), RenderableCollector::eWireframeOnly);
@@ -670,12 +670,6 @@ void Light::rotate(const Quaternion& rotation)
m_rotation.rotate(rotation);
}
-const Matrix4& Light::getLocalPivot() const {
- m_localPivot = m_rotation.getMatrix4();
- m_localPivot.t().getVector3() = _lightBox.origin;
- return m_localPivot;
-}
-
// greebo: This returns the AABB of the WHOLE light (this includes the volume and all its selectable vertices)
// Used to test the light for selection on mouse click.
const AABB& Light::localAABB() const
diff --git a/plugins/entity/light/Light.h b/plugins/entity/light/Light.h
index 59b1383..244e845 100644
--- a/plugins/entity/light/Light.h
+++ b/plugins/entity/light/Light.h
@@ -46,7 +46,6 @@ class LightNode;
class Light :
public OpenGLRenderable,
public Bounded,
- public Editable,
public Snappable
{
friend class LightNode;
@@ -244,10 +243,6 @@ public:
void revertTransform();
void freezeTransform();
- // note: move this
- mutable Matrix4 m_localPivot;
- const Matrix4& getLocalPivot() const;
-
// Is this light projected or omni?
bool isProjected() const;
diff --git a/plugins/entity/light/LightNode.cpp b/plugins/entity/light/LightNode.cpp
index c7a964e..571ffb0 100644
--- a/plugins/entity/light/LightNode.cpp
+++ b/plugins/entity/light/LightNode.cpp
@@ -57,10 +57,6 @@ void LightNode::construct()
_light.construct();
}
-const Matrix4& LightNode::getLocalPivot() const {
- return _light.getLocalPivot();
-}
-
// Snappable implementation
void LightNode::snapto(float snap) {
_light.snapto(snap);
@@ -142,6 +138,19 @@ void LightNode::setSelectedComponents(bool select, SelectionSystem::EComponentMo
}
}
+void LightNode::invertSelectedComponents(SelectionSystem::EComponentMode mode)
+{
+ if (mode == SelectionSystem::eVertex)
+ {
+ _lightCenterInstance.invertSelected();
+ _lightTargetInstance.invertSelected();
+ _lightRightInstance.invertSelected();
+ _lightUpInstance.invertSelected();
+ _lightStartInstance.invertSelected();
+ _lightEndInstance.invertSelected();
+ }
+}
+
void LightNode::testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
{
if (mode == SelectionSystem::eVertex)
@@ -251,7 +260,7 @@ scene::INodePtr LightNode::clone() const
return node;
}
-void LightNode::selectedChangedComponent(const Selectable& selectable) {
+void LightNode::selectedChangedComponent(const ISelectable& selectable) {
// add the selectable to the list of selected components (see RadiantSelectionSystem::onComponentSelection)
GlobalSelectionSystem().onComponentSelection(Node::getSelf(), selectable);
}
diff --git a/plugins/entity/light/LightNode.h b/plugins/entity/light/LightNode.h
index befaac9..278c819 100644
--- a/plugins/entity/light/LightNode.h
+++ b/plugins/entity/light/LightNode.h
@@ -17,7 +17,6 @@ class LightNode :
public EntityNode,
public ILightNode,
public Snappable,
- public Editable,
public ComponentSelectionTestable,
public ComponentEditable,
public ComponentSnappable,
@@ -61,9 +60,6 @@ public:
virtual void onInsertIntoScene(scene::IMapRootNode& root) override;
virtual void onRemoveFromScene(scene::IMapRootNode& root) override;
- // Editable implementation
- virtual const Matrix4& getLocalPivot() const;
-
// Snappable implementation
virtual void snapto(float snap);
@@ -95,10 +91,11 @@ public:
void testSelect(Selector& selector, SelectionTest& test);
// greebo: Returns true if drag planes or the light center is selected (both are components)
- bool isSelectedComponents() const;
+ bool isSelectedComponents() const override;
// greebo: Selects/deselects all components, depending on the chosen componentmode
- void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode);
- void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode);
+ void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) override;
+ void invertSelectedComponents(SelectionSystem::EComponentMode mode) override;
+ void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) override;
/**
* greebo: This returns the AABB of all the selectable vertices. This method
@@ -109,15 +106,15 @@ public:
scene::INodePtr clone() const;
- void selectedChangedComponent(const Selectable& selectable);
+ void selectedChangedComponent(const ISelectable& selectable);
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
// Renders the components of this light instance
- void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const override;
// RendererLight implementation
const Vector3& worldOrigin() const;
diff --git a/plugins/entity/speaker/SpeakerNode.cpp b/plugins/entity/speaker/SpeakerNode.cpp
index c7d3f84..f06e432 100644
--- a/plugins/entity/speaker/SpeakerNode.cpp
+++ b/plugins/entity/speaker/SpeakerNode.cpp
@@ -199,7 +199,7 @@ void SpeakerNode::testSelect(Selector& selector, SelectionTest& test)
}
}
-void SpeakerNode::selectedChangedComponent(const Selectable& selectable)
+void SpeakerNode::selectedChangedComponent(const ISelectable& selectable)
{
// add the selectable to the list of selected components (see RadiantSelectionSystem::onComponentSelection)
GlobalSelectionSystem().onComponentSelection(Node::getSelf(), selectable);
@@ -218,6 +218,11 @@ void SpeakerNode::setSelectedComponents(bool select, SelectionSystem::EComponent
}
}
+void SpeakerNode::invertSelectedComponents(SelectionSystem::EComponentMode mode)
+{
+ // nothing, planes are selected via selectPlanes()
+}
+
void SpeakerNode::testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode)
{
// nothing, planes are selected via selectPlanes()
diff --git a/plugins/entity/speaker/SpeakerNode.h b/plugins/entity/speaker/SpeakerNode.h
index 0f448a2..f67ba16 100644
--- a/plugins/entity/speaker/SpeakerNode.h
+++ b/plugins/entity/speaker/SpeakerNode.h
@@ -96,9 +96,10 @@ public:
void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes);
// ComponentSelectionTestable implementation
- bool isSelectedComponents() const;
- void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode);
- void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode);
+ bool isSelectedComponents() const override;
+ void setSelectedComponents(bool selected, SelectionSystem::EComponentMode mode) override;
+ void invertSelectedComponents(SelectionSystem::EComponentMode mode) override;
+ void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) override;
// SelectionTestable implementation
void testSelect(Selector& selector, SelectionTest& test);
@@ -106,10 +107,10 @@ public:
scene::INodePtr clone() const;
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
- void selectedChangedComponent(const Selectable& selectable);
+ void selectedChangedComponent(const ISelectable& selectable);
protected:
// Gets called by the Transformable implementation whenever
diff --git a/plugins/entity/target/TargetLineNode.cpp b/plugins/entity/target/TargetLineNode.cpp
index 6f90676..478fadb 100644
--- a/plugins/entity/target/TargetLineNode.cpp
+++ b/plugins/entity/target/TargetLineNode.cpp
@@ -43,11 +43,11 @@ void TargetLineNode::renderWireframe(RenderableCollector& collector, const Volum
_targetLines.render(collector, volume, getOwnerPosition());
}
-bool TargetLineNode::isHighlighted() const
+std::size_t TargetLineNode::getHighlightFlags()
{
- // We don't need to return true, since the render system will use
+ // We don't need to return highlighting, since the render system will use
// the result of the parent entity node
- return false;
+ return Highlight::NoHighlight;
}
const Vector3& TargetLineNode::getOwnerPosition() const
diff --git a/plugins/entity/target/TargetLineNode.h b/plugins/entity/target/TargetLineNode.h
index 1bde596..52ad7be 100644
--- a/plugins/entity/target/TargetLineNode.h
+++ b/plugins/entity/target/TargetLineNode.h
@@ -38,7 +38,7 @@ public:
void renderSolid(RenderableCollector& collector, const VolumeTest& volumeTest) const override;
void renderWireframe(RenderableCollector& collector, const VolumeTest& volumeTest) const override;
- bool isHighlighted() const override;
+ std::size_t getHighlightFlags() override;
private:
const Vector3& getOwnerPosition() const;
diff --git a/plugins/entity/target/TargetableNode.cpp b/plugins/entity/target/TargetableNode.cpp
index c426f60..5f66413 100644
--- a/plugins/entity/target/TargetableNode.cpp
+++ b/plugins/entity/target/TargetableNode.cpp
@@ -124,6 +124,9 @@ void TargetableNode::onTargetKeyCollectionChanged()
{
_targetLineNode.reset(new TargetLineNode(_node));
scene::addNodeToContainer(_targetLineNode, _node.shared_from_this());
+
+ // Fix #4373: Move the target lines to the same layers as the owning node
+ _targetLineNode->assignToLayers(_node.getLayers());
}
}
else // No more targets
diff --git a/plugins/entitylist/EntityList.cpp b/plugins/entitylist/EntityList.cpp
index 9773e68..5d757be 100644
--- a/plugins/entitylist/EntityList.cpp
+++ b/plugins/entitylist/EntityList.cpp
@@ -299,7 +299,7 @@ void EntityList::onSelection(wxDataViewEvent& ev)
wxutil::TreeModel::Row row(*i, *_treeModel.getModel());
scene::INode* node = static_cast<scene::INode*>(row[_treeModel.getColumns().node].getPointer());
- Selectable* selectable = dynamic_cast<Selectable*>(node);
+ ISelectable* selectable = dynamic_cast<ISelectable*>(node);
if (selectable != NULL)
{
diff --git a/plugins/entitylist/GraphTreeModelPopulator.h b/plugins/entitylist/GraphTreeModelPopulator.h
index b45cc2a..a07df67 100644
--- a/plugins/entitylist/GraphTreeModelPopulator.h
+++ b/plugins/entitylist/GraphTreeModelPopulator.h
@@ -41,7 +41,7 @@ public:
Entity* ent = Node_getEntity(node);
- if (ent != NULL && ent->getKeyValue("classname") == "worldspawn") {
+ if (ent != NULL && ent->isWorldspawn()) {
// Don't accumulate the worldspawn brushes
return false;
}
diff --git a/plugins/eventmanager/MouseToolManager.cpp b/plugins/eventmanager/MouseToolManager.cpp
index e2acc3c..212ec96 100644
--- a/plugins/eventmanager/MouseToolManager.cpp
+++ b/plugins/eventmanager/MouseToolManager.cpp
@@ -42,58 +42,53 @@ void MouseToolManager::initialiseModule(const ApplicationContext& ctx)
sigc::mem_fun(this, &MouseToolManager::onRadiantStartup));
}
-void MouseToolManager::loadGroupMapping(MouseToolGroup& group, const xml::Node& mappingNode)
+void MouseToolManager::loadGroupMapping(MouseToolGroup::Type type, const xml::NodeList& userMappings, const xml::NodeList& defaultMappings)
{
- group.clearToolMappings();
-
- for (const xml::Node& node : mappingNode.getNamedChildren("tool"))
- {
- // Load the condition
- unsigned int state = wxutil::MouseButton::LoadFromNode(node) | wxutil::Modifier::LoadFromNode(node);
- std::string name = node.getAttributeValue("name");
- MouseToolPtr tool = group.getMouseToolByName(name);
-
- if (!tool)
- {
- rWarning() << "Unregistered MouseTool name in XML for group " <<
- static_cast<int>(group.getType()) << ": " << name << std::endl;
- continue;
- }
-
- group.addToolMapping(state, tool);
- }
+ MouseToolGroup& group = getGroup(type);
+
+ group.clearToolMappings();
+
+ group.foreachMouseTool([&] (const MouseToolPtr& tool)
+ {
+ // First, look in the userMappings if we have a user-defined setting
+ for (const xml::Node& node : userMappings)
+ {
+ if (node.getAttributeValue("name") == tool->getName())
+ {
+ // Load the condition
+ unsigned int state = wxutil::MouseButton::LoadFromNode(node) | wxutil::Modifier::LoadFromNode(node);
+ group.addToolMapping(state, tool);
+
+ return; // done here
+ }
+ }
+
+ // nothing found in the user mapping, fall back to default
+ for (const xml::Node& node : defaultMappings)
+ {
+ if (node.getAttributeValue("name") == tool->getName())
+ {
+ // Load the condition
+ unsigned int state = wxutil::MouseButton::LoadFromNode(node) | wxutil::Modifier::LoadFromNode(node);
+ group.addToolMapping(state, tool);
+
+ return; // done here
+ }
+ }
+
+ // No mapping for this tool
+ });
}
void MouseToolManager::loadToolMappings()
{
// All modules have registered their stuff, now load the mapping
// Try the user-defined mapping first
- xml::NodeList mappings = GlobalRegistry().findXPath("user/ui/input/mouseToolMappings[@name='user']//mouseToolMapping");
-
- if (mappings.empty())
- {
- // Fall back to the default mapping
- mappings = GlobalRegistry().findXPath("user/ui/input/mouseToolMappings[@name='default']//mouseToolMapping");
- }
+ xml::NodeList userMappings = GlobalRegistry().findXPath("user/ui/input/mouseToolMappings[@name='user']//mouseToolMapping//tool");
+ xml::NodeList defaultMappings = GlobalRegistry().findXPath("user/ui/input/mouseToolMappings[@name='default']//mouseToolMapping//tool");
- for (const xml::Node& node : mappings)
- {
- std::string mappingName = node.getAttributeValue("name");
-
- int mappingId = string::convert<int>(node.getAttributeValue("id"), -1);
-
- if (mappingId == -1)
- {
- rMessage() << "Skipping invalid view id in mouse tool mapping " << mappingName << std::endl;
- continue;
- }
-
- rMessage() << "Loading mouse tool mapping for " << mappingName << std::endl;
-
- MouseToolGroup::Type type = static_cast<MouseToolGroup::Type>(mappingId);
-
- loadGroupMapping(getGroup(type), node);
- }
+ loadGroupMapping(MouseToolGroup::Type::CameraView, userMappings, defaultMappings);
+ loadGroupMapping(MouseToolGroup::Type::OrthoView, userMappings, defaultMappings);
}
void MouseToolManager::resetBindingsToDefault()
diff --git a/plugins/eventmanager/MouseToolManager.h b/plugins/eventmanager/MouseToolManager.h
index d545c99..550c396 100644
--- a/plugins/eventmanager/MouseToolManager.h
+++ b/plugins/eventmanager/MouseToolManager.h
@@ -47,7 +47,7 @@ public:
private:
void loadToolMappings();
- void loadGroupMapping(MouseToolGroup& group, const xml::Node& mappingNode);
+ void loadGroupMapping(MouseToolGroup::Type type, const xml::NodeList& userMappings, const xml::NodeList& defaultMappings);
void saveToolMappings();
};
diff --git a/plugins/fonts/GlyphSet.cpp b/plugins/fonts/GlyphSet.cpp
index 52a5724..1f54179 100644
--- a/plugins/fonts/GlyphSet.cpp
+++ b/plugins/fonts/GlyphSet.cpp
@@ -68,7 +68,7 @@ GlyphSetPtr GlyphSet::createFromDatFile(const std::string& vfsPath,
q3font::Q3FontInfoPtr buf(new q3font::Q3FontInfo);
InputStream& stream = file->getInputStream();
- StreamBase::size_type bytesRead = stream.read(
+ stream.read(
reinterpret_cast<StreamBase::byte_type*>(buf.get()),
sizeof(q3font::Q3FontInfo)
);
diff --git a/plugins/fonts/Makefile.am b/plugins/fonts/Makefile.am
index 2699ad8..2ea17c4 100644
--- a/plugins/fonts/Makefile.am
+++ b/plugins/fonts/Makefile.am
@@ -10,6 +10,8 @@ fonts_la_LDFLAGS = -module -avoid-version \
$(XML_LIBS) \
$(GL_LIBS) \
$(GLU_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(BOOST_REGEX_LIBS) \
$(LIBSIGC_LIBS)
fonts_la_SOURCES = plugin.cpp \
diff --git a/plugins/fonts/Makefile.in b/plugins/fonts/Makefile.in
index 914819a..b0ede33 100644
--- a/plugins/fonts/Makefile.in
+++ b/plugins/fonts/Makefile.in
@@ -408,6 +408,8 @@ fonts_la_LDFLAGS = -module -avoid-version \
$(XML_LIBS) \
$(GL_LIBS) \
$(GLU_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(BOOST_REGEX_LIBS) \
$(LIBSIGC_LIBS)
diff --git a/plugins/grid/Grid.cpp b/plugins/grid/Grid.cpp
index 2e8bf62..cb78edd 100644
--- a/plugins/grid/Grid.cpp
+++ b/plugins/grid/Grid.cpp
@@ -52,7 +52,7 @@ public:
rMessage() << "GridManager::initialiseModule called.\n";
// Add the grid status bar element
- GlobalUIManager().getStatusBarManager().addTextElement("GridStatus", "grid_up.png", IStatusBarManager::POS_GRID);
+ GlobalUIManager().getStatusBarManager().addTextElement("GridStatus", "grid_up.png", IStatusBarManager::POS_GRID, _("Current Grid Size"));
GlobalUIManager().getStatusBarManager().setText("GridStatus", "-");
populateGridItems();
@@ -147,10 +147,11 @@ public:
return returnValue;
}
- void constructPreferences() {
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Grid"));
+ void constructPreferences()
+ {
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Grid"));
- page->appendCombo(_("Default Grid Size"), RKEY_DEFAULT_GRID_SIZE, getGridList());
+ page.appendCombo(_("Default Grid Size"), RKEY_DEFAULT_GRID_SIZE, getGridList());
ComboBoxValueList looks;
@@ -162,8 +163,8 @@ public:
looks.push_back(_("Big Dots"));
looks.push_back(_("Squares"));
- page->appendCombo(_("Major Grid Style"), RKEY_GRID_LOOK_MAJOR, looks);
- page->appendCombo(_("Minor Grid Style"), RKEY_GRID_LOOK_MINOR, looks);
+ page.appendCombo(_("Major Grid Style"), RKEY_GRID_LOOK_MAJOR, looks);
+ page.appendCombo(_("Minor Grid Style"), RKEY_GRID_LOOK_MINOR, looks);
}
diff --git a/plugins/mapdoom3/Makefile.am b/plugins/mapdoom3/Makefile.am
index 2692331..5284dcb 100644
--- a/plugins/mapdoom3/Makefile.am
+++ b/plugins/mapdoom3/Makefile.am
@@ -9,7 +9,12 @@ mapdoom3_la_LIBADD = $(top_builddir)/libs/wxutil/libwxutil.la \
$(top_builddir)/libs/scene/libscenegraph.la \
$(top_builddir)/libs/math/libmath.la
mapdoom3_la_LDFLAGS = -module -avoid-version \
- $(WX_LIBS) $(XML_LIBS) $(GLEW_LIBS) $(GL_LIBS)
+ $(WX_LIBS) \
+ $(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(GLEW_LIBS) \
+ $(GL_LIBS)
mapdoom3_la_SOURCES = Doom3MapFormat.cpp \
Doom3PrefabFormat.cpp \
Quake3MapFormat.cpp \
@@ -27,6 +32,9 @@ mapdoom3_la_SOURCES = Doom3MapFormat.cpp \
compiler/ProcWinding.cpp \
compiler/ProcLight.cpp \
compiler/Surface.cpp \
+ aas/Doom3AasFile.cpp \
+ aas/Doom3AasFileLoader.cpp \
+ aas/Doom3AasFileSettings.cpp \
primitiveparsers/BrushDef.cpp \
primitiveparsers/BrushDef3.cpp \
primitiveparsers/Patch.cpp \
diff --git a/plugins/mapdoom3/Makefile.in b/plugins/mapdoom3/Makefile.in
index ca93772..7fda851 100644
--- a/plugins/mapdoom3/Makefile.in
+++ b/plugins/mapdoom3/Makefile.in
@@ -138,9 +138,11 @@ am_mapdoom3_la_OBJECTS = Doom3MapFormat.lo Doom3PrefabFormat.lo \
compiler/OptIsland.lo compiler/ProcCompiler.lo \
compiler/ProcFile.lo compiler/ProcPatch.lo \
compiler/ProcWinding.lo compiler/ProcLight.lo \
- compiler/Surface.lo primitiveparsers/BrushDef.lo \
- primitiveparsers/BrushDef3.lo primitiveparsers/Patch.lo \
- primitiveparsers/PatchDef2.lo primitiveparsers/PatchDef3.lo
+ compiler/Surface.lo aas/Doom3AasFile.lo \
+ aas/Doom3AasFileLoader.lo aas/Doom3AasFileSettings.lo \
+ primitiveparsers/BrushDef.lo primitiveparsers/BrushDef3.lo \
+ primitiveparsers/Patch.lo primitiveparsers/PatchDef2.lo \
+ primitiveparsers/PatchDef3.lo
mapdoom3_la_OBJECTS = $(am_mapdoom3_la_OBJECTS)
AM_V_lt = $(am__v_lt_ at AM_V@)
am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -420,7 +422,12 @@ mapdoom3_la_LIBADD = $(top_builddir)/libs/wxutil/libwxutil.la \
$(top_builddir)/libs/math/libmath.la
mapdoom3_la_LDFLAGS = -module -avoid-version \
- $(WX_LIBS) $(XML_LIBS) $(GLEW_LIBS) $(GL_LIBS)
+ $(WX_LIBS) \
+ $(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(GLEW_LIBS) \
+ $(GL_LIBS)
mapdoom3_la_SOURCES = Doom3MapFormat.cpp \
Doom3PrefabFormat.cpp \
@@ -439,6 +446,9 @@ mapdoom3_la_SOURCES = Doom3MapFormat.cpp \
compiler/ProcWinding.cpp \
compiler/ProcLight.cpp \
compiler/Surface.cpp \
+ aas/Doom3AasFile.cpp \
+ aas/Doom3AasFileLoader.cpp \
+ aas/Doom3AasFileSettings.cpp \
primitiveparsers/BrushDef.cpp \
primitiveparsers/BrushDef3.cpp \
primitiveparsers/Patch.cpp \
@@ -536,6 +546,17 @@ compiler/ProcLight.lo: compiler/$(am__dirstamp) \
compiler/$(DEPDIR)/$(am__dirstamp)
compiler/Surface.lo: compiler/$(am__dirstamp) \
compiler/$(DEPDIR)/$(am__dirstamp)
+aas/$(am__dirstamp):
+ @$(MKDIR_P) aas
+ @: > aas/$(am__dirstamp)
+aas/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) aas/$(DEPDIR)
+ @: > aas/$(DEPDIR)/$(am__dirstamp)
+aas/Doom3AasFile.lo: aas/$(am__dirstamp) aas/$(DEPDIR)/$(am__dirstamp)
+aas/Doom3AasFileLoader.lo: aas/$(am__dirstamp) \
+ aas/$(DEPDIR)/$(am__dirstamp)
+aas/Doom3AasFileSettings.lo: aas/$(am__dirstamp) \
+ aas/$(DEPDIR)/$(am__dirstamp)
primitiveparsers/$(am__dirstamp):
@$(MKDIR_P) primitiveparsers
@: > primitiveparsers/$(am__dirstamp)
@@ -558,6 +579,8 @@ mapdoom3.la: $(mapdoom3_la_OBJECTS) $(mapdoom3_la_DEPENDENCIES) $(EXTRA_mapdoom3
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f aas/*.$(OBJEXT)
+ -rm -f aas/*.lo
-rm -f compiler/*.$(OBJEXT)
-rm -f compiler/*.lo
-rm -f primitiveparsers/*.$(OBJEXT)
@@ -575,6 +598,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Quake4MapFormat.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/Quake4MapReader.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mapdoom3.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at aas/$(DEPDIR)/Doom3AasFile.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at aas/$(DEPDIR)/Doom3AasFileLoader.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at aas/$(DEPDIR)/Doom3AasFileSettings.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at compiler/$(DEPDIR)/Doom3MapCompiler.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at compiler/$(DEPDIR)/OptIsland.Plo at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at compiler/$(DEPDIR)/ProcCompiler.Plo at am__quote@
@@ -618,6 +644,7 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+ -rm -rf aas/.libs aas/_libs
-rm -rf compiler/.libs compiler/_libs
-rm -rf primitiveparsers/.libs primitiveparsers/_libs
@@ -736,6 +763,8 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f aas/$(DEPDIR)/$(am__dirstamp)
+ -rm -f aas/$(am__dirstamp)
-rm -f compiler/$(DEPDIR)/$(am__dirstamp)
-rm -f compiler/$(am__dirstamp)
-rm -f primitiveparsers/$(DEPDIR)/$(am__dirstamp)
@@ -750,7 +779,7 @@ clean-am: clean-generic clean-libtool clean-modulesLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR) compiler/$(DEPDIR) primitiveparsers/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) aas/$(DEPDIR) compiler/$(DEPDIR) primitiveparsers/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -796,7 +825,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR) compiler/$(DEPDIR) primitiveparsers/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) aas/$(DEPDIR) compiler/$(DEPDIR) primitiveparsers/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/plugins/mapdoom3/aas/Doom3AasFile.cpp b/plugins/mapdoom3/aas/Doom3AasFile.cpp
new file mode 100644
index 0000000..5e7d4b0
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFile.cpp
@@ -0,0 +1,413 @@
+#include "Doom3AasFile.h"
+
+#include "itextstream.h"
+#include "string/convert.h"
+#include "Util.h"
+
+namespace map
+{
+
+// area flags
+#define AREA_FLOOR (1 << 0) // AI can stand on the floor in this area
+#define AREA_GAP (1 << 1) // area has a gap
+#define AREA_LEDGE (1 << 2) // if entered the AI bbox partly floats above a ledge
+#define AREA_LADDER (1 << 3) // area contains one or more ladder faces
+#define AREA_LIQUID (1 << 4) // area contains a liquid
+#define AREA_CROUCH (1 << 5) // AI cannot walk but can only crouch in this area
+#define AREA_REACHABLE_WALK (1 << 6) // area is reachable by walking or swimming
+#define AREA_REACHABLE_FLY (1 << 7) // area is reachable by flying
+#define AREA_DOOR (1 << 8) // area contains one ore more doors
+
+// face flags
+#define FACE_SOLID (1 << 0) // solid at the other side
+#define FACE_LADDER (1 << 1) // ladder surface
+#define FACE_FLOOR (1 << 2) // standing on floor when on this face
+#define FACE_LIQUID (1 << 3) // face seperating two areas with liquid
+#define FACE_LIQUIDSURFACE (1 << 4) // face seperating liquid and air
+
+std::size_t Doom3AasFile::getNumPlanes() const
+{
+ return _planes.size();
+}
+
+const Plane3& Doom3AasFile::getPlane(std::size_t planeNum) const
+{
+ return _planes[planeNum];
+}
+
+std::size_t Doom3AasFile::getNumVertices() const
+{
+ return _vertices.size();
+}
+
+const Vector3& Doom3AasFile::getVertex(std::size_t vertexNum) const
+{
+ return _vertices[vertexNum];
+}
+
+std::size_t Doom3AasFile::getNumEdges() const
+{
+ return _edges.size();
+}
+
+const IAasFile::Edge& Doom3AasFile::getEdge(std::size_t index) const
+{
+ return _edges[index];
+}
+
+std::size_t Doom3AasFile::getNumEdgeIndexes() const
+{
+ return _edgeIndex.size();
+}
+
+int Doom3AasFile::getEdgeByIndex(int edgeIdx) const
+{
+ return _edgeIndex[edgeIdx];
+}
+
+std::size_t Doom3AasFile::getNumFaces() const
+{
+ return _faces.size();
+}
+
+const IAasFile::Face& Doom3AasFile::getFace(int faceIndex) const
+{
+ return _faces[faceIndex];
+}
+
+std::size_t Doom3AasFile::getNumFaceIndexes() const
+{
+ return _faceIndex.size();
+}
+
+int Doom3AasFile::getFaceByIndex(int faceIdx) const
+{
+ return _faceIndex[faceIdx];
+}
+
+std::size_t Doom3AasFile::getNumAreas() const
+{
+ return _areas.size();
+}
+
+const IAasFile::Area& Doom3AasFile::getArea(int areaNum) const
+{
+ return _areas[areaNum];
+}
+
+void Doom3AasFile::parseFromTokens(parser::DefTokeniser& tok)
+{
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == "settings")
+ {
+ _settings.parseFromTokens(tok);
+ }
+ else if (token == "planes")
+ {
+ std::size_t planesCount = string::convert<std::size_t>(tok.nextToken());
+
+ _planes.reserve(planesCount);
+
+ tok.assertNextToken("{");
+
+ // num ( a b c dist )
+ for (std::size_t i = 0; i < planesCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // plane index
+
+ tok.assertNextToken("(");
+
+ Plane3 plane;
+ plane.normal().x() = string::convert<Vector3::ElementType>(tok.nextToken());
+ plane.normal().y() = string::convert<Vector3::ElementType>(tok.nextToken());
+ plane.normal().z() = string::convert<Vector3::ElementType>(tok.nextToken());
+ plane.dist() = string::convert<Vector3::ElementType>(tok.nextToken());
+
+ _planes.push_back(plane);
+
+ tok.assertNextToken(")");
+ }
+
+ tok.assertNextToken("}");
+ }
+ else if (token == "vertices")
+ {
+ std::size_t vertCount = string::convert<std::size_t>(tok.nextToken());
+
+ _vertices.reserve(vertCount);
+
+ tok.assertNextToken("{");
+
+ // num ( x y z )
+ for (std::size_t i = 0; i < vertCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // index
+ _vertices.push_back(parseVector3(tok)); // components
+ }
+
+ tok.assertNextToken("}");
+ }
+ else if (token == "edges")
+ {
+ std::size_t edgeCount = string::convert<std::size_t>(tok.nextToken());
+
+ _edges.reserve(edgeCount);
+
+ tok.assertNextToken("{");
+
+ // num ( vertIdx1 vertIdx2 )
+ for (std::size_t i = 0; i < edgeCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // index
+
+ tok.assertNextToken("(");
+
+ Edge edge;
+ edge.vertexNumber[0] = string::convert<int>(tok.nextToken());
+ edge.vertexNumber[1] = string::convert<int>(tok.nextToken());
+
+ tok.assertNextToken(")");
+
+ _edges.push_back(edge); // components
+ }
+
+ tok.assertNextToken("}");
+ }
+ else if (token == "edgeIndex")
+ {
+ parseIndex(tok, _edgeIndex);
+ }
+ else if (token == "faces")
+ {
+ std::size_t faceCount = string::convert<std::size_t>(tok.nextToken());
+
+ _faces.reserve(faceCount);
+
+ tok.assertNextToken("{");
+
+ // num ( planeNum flags areas[0] areas[1] firstEdge numEdges )
+ for (std::size_t i = 0; i < faceCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // number
+
+ tok.assertNextToken("(");
+
+ Face face;
+
+ face.planeNum = string::convert<int>(tok.nextToken());
+ face.flags = string::convert<int>(tok.nextToken());
+ face.areas[0] = string::convert<int>(tok.nextToken());
+ face.areas[1] = string::convert<int>(tok.nextToken());
+ face.firstEdge = string::convert<int>(tok.nextToken());
+ face.numEdges = string::convert<int>(tok.nextToken());
+
+ _faces.push_back(face);
+
+ tok.assertNextToken(")");
+ }
+
+ tok.assertNextToken("}");
+ }
+ else if (token == "faceIndex")
+ {
+ parseIndex(tok, _faceIndex);
+ }
+ else if (token == "areas")
+ {
+ std::size_t areaCount = string::convert<std::size_t>(tok.nextToken());
+
+ _areas.reserve(areaCount);
+
+ tok.assertNextToken("{");
+
+ // num ( flags contents firstFace numFaces cluster clusterAreaNum ) reachabilityCount { reachabilities }
+ for (std::size_t i = 0; i < areaCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // number
+
+ tok.assertNextToken("(");
+
+ Area area;
+
+ area.flags = string::convert<int>(tok.nextToken());
+ area.contents = string::convert<int>(tok.nextToken());
+ area.firstFace = string::convert<int>(tok.nextToken());
+ area.numFaces = string::convert<int>(tok.nextToken());
+ area.cluster = string::convert<int>(tok.nextToken());
+ area.clusterAreaNum = string::convert<int>(tok.nextToken());
+
+ _areas.push_back(area);
+
+ tok.assertNextToken(")");
+
+ // Skip over reachabilities for the moment being
+ /*std::size_t reachCount = */string::convert<std::size_t>(tok.nextToken());
+ tok.assertNextToken("{");
+
+ while (tok.nextToken() != "}")
+ {
+ // do nothing
+ }
+ }
+
+ // Skip the step LinkReversedReachability();
+
+ tok.assertNextToken("}");
+ }
+ else if (token == "nodes" || token == "portals" || token == "portalIndex" || token == "clusters")
+ {
+ tok.nextToken(); // integer
+ tok.assertNextToken("{");
+
+ while (tok.nextToken() != "}")
+ {
+ // do nothing
+ }
+ }
+ else
+ {
+ throw parser::ParseException("Unknown token: " + token);
+ }
+ }
+
+ finishAreas();
+}
+
+void Doom3AasFile::finishAreas()
+{
+ for (Area& area : _areas)
+ {
+ area.center = calcReachableGoalForArea(area);
+ area.bounds = calcAreaBounds(area);
+ }
+}
+
+#define INTSIGNBITSET(i) (((const unsigned int)(i)) >> 31)
+
+AABB Doom3AasFile::calcFaceBounds(int faceNum) const
+{
+ AABB bounds;
+
+ const Face& face = _faces[faceNum];
+
+ for (int i = 0; i < face.numEdges; i++)
+ {
+ int edgeNum = _edgeIndex[face.firstEdge + i];
+ const Edge& edge = _edges[abs(edgeNum)];
+
+ bounds.includePoint(_vertices[edge.vertexNumber[INTSIGNBITSET(edgeNum)]]);
+ }
+ return bounds;
+}
+
+AABB Doom3AasFile::calcAreaBounds(const IAasFile::Area& area) const
+{
+ AABB bounds;
+
+ for (int i = 0; i < area.numFaces; i++)
+ {
+ int faceNum = _faceIndex[area.firstFace + i];
+ bounds.includeAABB(calcFaceBounds(abs(faceNum)));
+ }
+
+ return bounds;
+}
+
+Vector3 Doom3AasFile::calcFaceCenter(int faceNum) const
+{
+ Vector3 center(0,0,0);
+
+ const Face& face = _faces[faceNum];
+
+ if (face.numEdges > 0)
+ {
+ for (int i = 0; i < face.numEdges; i++)
+ {
+ int edgeNum = _edgeIndex[face.firstEdge + i];
+ const Edge& edge = _edges[abs(edgeNum)];
+
+ center += _vertices[edge.vertexNumber[INTSIGNBITSET(edgeNum)]];
+ }
+ center /= face.numEdges;
+ }
+
+ return center;
+}
+
+Vector3 Doom3AasFile::calcAreaCenter(const IAasFile::Area& area) const
+{
+ Vector3 center(0,0,0);
+
+ if (area.numFaces > 0)
+ {
+ for (int i = 0; i < area.numFaces; i++)
+ {
+ int faceNum = _faceIndex[area.firstFace + i];
+ center += calcFaceCenter(abs(faceNum));
+ }
+
+ center /= area.numFaces;
+ }
+
+ return center;
+}
+
+Vector3 Doom3AasFile::calcReachableGoalForArea(const IAasFile::Area& area) const
+{
+ if (!(area.flags & (AREA_REACHABLE_WALK|AREA_REACHABLE_FLY)) || (area.flags & AREA_LIQUID))
+ {
+ return calcAreaCenter(area);
+ }
+
+ Vector3 center(0,0,0);
+
+ int numFaces = 0;
+
+ for (int i = 0; i < area.numFaces; i++)
+ {
+ int faceNum = _faceIndex[area.firstFace + i];
+
+ if (!(_faces[abs(faceNum)].flags & FACE_FLOOR))
+ {
+ continue;
+ }
+
+ center += calcFaceCenter(abs(faceNum));
+ numFaces++;
+ }
+
+ if (numFaces > 0)
+ {
+ center /= numFaces;
+ }
+
+ // No downward trace here
+
+ return center;
+}
+
+void Doom3AasFile::parseIndex(parser::DefTokeniser& tok, Index& index)
+{
+ std::size_t idxCount = string::convert<std::size_t>(tok.nextToken());
+
+ index.reserve(idxCount);
+
+ tok.assertNextToken("{");
+
+ // num ( idx )
+ for (std::size_t i = 0; i < idxCount; ++i)
+ {
+ string::convert<int>(tok.nextToken()); // number
+
+ tok.assertNextToken("(");
+ index.push_back(string::convert<int>(tok.nextToken()));
+ tok.assertNextToken(")");
+ }
+
+ tok.assertNextToken("}");
+}
+
+}
diff --git a/plugins/mapdoom3/aas/Doom3AasFile.h b/plugins/mapdoom3/aas/Doom3AasFile.h
new file mode 100644
index 0000000..2228678
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFile.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "iaasfile.h"
+#include "parser/DefTokeniser.h"
+#include "Doom3AasFileSettings.h"
+#include <vector>
+#include "math/Plane3.h"
+#include "math/AABB.h"
+
+namespace map
+{
+
+class Doom3AasFile :
+ public IAasFile
+{
+private:
+ Doom3AasFileSettings _settings;
+
+ std::vector<Plane3> _planes;
+ std::vector<Vector3> _vertices;
+ std::vector<Edge> _edges;
+
+ typedef std::vector<int> Index;
+ Index _edgeIndex;
+
+ std::vector<Face> _faces;
+ Index _faceIndex;
+
+ std::vector<Area> _areas;
+
+public:
+ virtual std::size_t getNumPlanes() const override;
+ virtual const Plane3& getPlane(std::size_t planeNum) const;
+
+ virtual std::size_t getNumVertices() const override;
+ virtual const Vector3& getVertex(std::size_t vertexNum) const override;
+
+ virtual std::size_t getNumEdges() const override;
+ virtual const Edge& getEdge(std::size_t index) const override;
+
+ virtual std::size_t getNumEdgeIndexes() const override;
+ virtual int getEdgeByIndex(int edgeIdx) const override;
+
+ virtual std::size_t getNumFaces() const override;
+ virtual const Face& getFace(int faceIndex) const override;
+ virtual std::size_t getNumFaceIndexes() const override;
+ virtual int getFaceByIndex(int faceIdx) const override;
+
+ virtual std::size_t getNumAreas() const override;
+ virtual const Area& getArea(int areaNum) const override;
+
+ void parseFromTokens(parser::DefTokeniser& tok);
+
+private:
+ void parseIndex(parser::DefTokeniser& tok, Index& index);
+ void finishAreas();
+ Vector3 calcReachableGoalForArea(const IAasFile::Area& area) const;
+ Vector3 calcFaceCenter(int faceNum) const;
+ Vector3 calcAreaCenter(const IAasFile::Area& area) const;
+ AABB calcAreaBounds(const IAasFile::Area& area) const;
+ AABB calcFaceBounds(int faceNum) const;
+};
+typedef std::shared_ptr<Doom3AasFile> Doom3AasFilePtr;
+
+}
diff --git a/plugins/mapdoom3/aas/Doom3AasFileLoader.cpp b/plugins/mapdoom3/aas/Doom3AasFileLoader.cpp
new file mode 100644
index 0000000..15b0302
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFileLoader.cpp
@@ -0,0 +1,127 @@
+#include "Doom3AasFileLoader.h"
+
+#include "itextstream.h"
+
+#include "parser/DefTokeniser.h"
+#include "string/convert.h"
+#include "Doom3AasFile.h"
+
+namespace map
+{
+
+namespace
+{
+ const float DEWM3_AAS_VERSION = 1.07f;
+}
+
+const std::string& Doom3AasFileLoader::getAasFormatName() const
+{
+ static std::string _name = "Doom 3 AAS";
+ return _name;
+}
+
+const std::string& Doom3AasFileLoader::getGameType() const
+{
+ static std::string _gameType = "doom3";
+ return _gameType;
+}
+
+bool Doom3AasFileLoader::canLoad(std::istream& stream) const
+{
+ // Instantiate a tokeniser to read the first few tokens
+ parser::BasicDefTokeniser<std::istream> tok(stream);
+
+ try
+ {
+ parseVersion(tok);
+ }
+ catch (parser::ParseException&)
+ {
+ return false;
+ }
+ catch (boost::bad_lexical_cast&)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+IAasFilePtr Doom3AasFileLoader::loadFromStream(std::istream& stream)
+{
+ Doom3AasFilePtr aasFile = std::make_shared<Doom3AasFile>();
+
+ // We assume that the stream is rewound to the beginning
+
+ // Instantiate a tokeniser to read the version tag
+ parser::BasicDefTokeniser<std::istream> tok(stream);
+
+ try
+ {
+ // File header
+ parseVersion(tok);
+
+ // Checksum (will throw if the stirng conversion fails)
+ string::convert<long>(tok.nextToken());
+
+ aasFile->parseFromTokens(tok);
+ }
+ catch (parser::ParseException& ex)
+ {
+ rError() << "Failure parsing AAS file: " << ex.what() << std::endl;
+ return IAasFilePtr();
+ }
+ catch (boost::bad_lexical_cast& ex)
+ {
+ rError() << "Conversion error while parsing AAS file: " << ex.what() << std::endl;
+ return IAasFilePtr();
+ }
+
+ return aasFile;
+}
+
+void Doom3AasFileLoader::parseVersion(parser::DefTokeniser& tok) const
+{
+ // Require a "Version" token
+ tok.assertNextToken("DewmAAS");
+
+ // Require specific version, return true on success
+ if (string::convert<float>(tok.nextToken()) != DEWM3_AAS_VERSION)
+ {
+ throw parser::ParseException("AAS File version mismatch");
+ }
+}
+
+const std::string& Doom3AasFileLoader::getName() const
+{
+ static std::string _name("Doom3AasFileLoader");
+ return _name;
+}
+
+const StringSet& Doom3AasFileLoader::getDependencies() const
+{
+ static StringSet _dependencies;
+
+ if (_dependencies.empty())
+ {
+ _dependencies.insert(MODULE_AASFILEMANAGER);
+ }
+
+ return _dependencies;
+}
+
+void Doom3AasFileLoader::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << ": initialiseModule called." << std::endl;
+
+ // Register ourselves as aas format
+ GlobalAasFileManager().registerLoader(shared_from_this());
+}
+
+void Doom3AasFileLoader::shutdownModule()
+{
+ // Unregister now that we're shutting down
+ GlobalAasFileManager().unregisterLoader(shared_from_this());
+}
+
+}
diff --git a/plugins/mapdoom3/aas/Doom3AasFileLoader.h b/plugins/mapdoom3/aas/Doom3AasFileLoader.h
new file mode 100644
index 0000000..20ec209
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFileLoader.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "iaasfile.h"
+
+namespace parser { class DefTokeniser; }
+
+namespace map
+{
+
+/**
+ * A loader class designed to parse Doom 3 AAS Files.
+ */
+class Doom3AasFileLoader :
+ public IAasFileLoader,
+ public std::enable_shared_from_this<Doom3AasFileLoader>
+{
+public:
+ virtual const std::string& getAasFormatName() const override;
+ virtual const std::string& getGameType() const override;
+
+ virtual bool canLoad(std::istream& stream) const override;
+ virtual IAasFilePtr loadFromStream(std::istream& stream) override;
+
+ // RegisterableModule implementation
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
+ virtual void shutdownModule() override;
+
+private:
+ // Parses the file header, throws exception on failure
+ void parseVersion(parser::DefTokeniser& tok) const;
+};
+
+}
\ No newline at end of file
diff --git a/plugins/mapdoom3/aas/Doom3AasFileSettings.cpp b/plugins/mapdoom3/aas/Doom3AasFileSettings.cpp
new file mode 100644
index 0000000..915e35c
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFileSettings.cpp
@@ -0,0 +1,162 @@
+#include "Doom3AasFileSettings.h"
+
+#include "string/convert.h"
+#include <boost/algorithm/string/trim.hpp>
+#include "Util.h"
+
+namespace map
+{
+
+Doom3AasFileSettings::Doom3AasFileSettings() :
+ numBoundingBoxes(1),
+ usePatches(false),
+ writeBrushMap(false),
+ playerFlood(false),
+ noOptimize(false),
+ allowSwimReachabilities(false),
+ allowFlyReachabilities(false),
+ fileExtension("aas48"),
+ gravity(0, 0, -1066),
+ gravityDir(gravity.getNormalised()),
+ gravityValue(gravity.getLength()),
+ invGravityDir(-gravityDir),
+ maxStepHeight(14.0f),
+ maxBarrierHeight(32.0f),
+ maxWaterJumpHeight(20.0f),
+ maxFallHeight(64.0f),
+ minFloorCos(0.7f),
+ tt_barrierJump(100),
+ tt_startCrouching(100),
+ tt_waterJump(100),
+ tt_startWalkOffLedge(100)
+{
+ boundingBoxes[0] = AABB::createFromMinMax(Vector3(-16, -16, 0), Vector3(16, 16, 72));
+}
+
+void Doom3AasFileSettings::parseFromTokens(parser::DefTokeniser& tok)
+{
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == "}")
+ {
+ break;
+ }
+ else if (token == "bboxes")
+ {
+ // Parse bboxes
+ tok.assertNextToken("{");
+
+ std::size_t index = 0;
+
+ while (tok.hasMoreTokens() && index < MAX_AAS_BOUNDING_BOXES)
+ {
+ if (tok.peek() == "}")
+ {
+ tok.nextToken();
+ break;
+ }
+
+ // Parse bbox
+ boundingBoxes[index].origin = parseVector3(tok);
+ tok.assertNextToken("-");
+ boundingBoxes[index].extents = parseVector3(tok);
+
+ ++index;
+ }
+ }
+ else if (token == "usePatches")
+ {
+ tok.assertNextToken("=");
+ usePatches = string::convert<bool>(tok.nextToken());
+ }
+ else if (token == "writeBrushMap")
+ {
+ tok.assertNextToken("=");
+ writeBrushMap = string::convert<bool>(tok.nextToken());
+ }
+ else if (token == "playerFlood")
+ {
+ tok.assertNextToken("=");
+ playerFlood = string::convert<bool>(tok.nextToken());
+ }
+ else if (token == "allowSwimReachabilities")
+ {
+ tok.assertNextToken("=");
+ allowSwimReachabilities = string::convert<bool>(tok.nextToken());
+ }
+ else if (token == "allowFlyReachabilities")
+ {
+ tok.assertNextToken("=");
+ allowFlyReachabilities = string::convert<bool>(tok.nextToken());
+ }
+ else if (token == "fileExtension")
+ {
+ tok.assertNextToken("=");
+ fileExtension = boost::algorithm::trim_copy_if(tok.nextToken(), boost::algorithm::is_any_of("\""));
+ }
+ else if (token == "gravity")
+ {
+ tok.assertNextToken("=");
+ gravity = parseVector3(tok);
+
+ gravityDir = gravity.getNormalised();
+ gravityValue = gravity.getLength();
+ invGravityDir = -gravityDir;
+ }
+ else if (token == "maxStepHeight")
+ {
+ tok.assertNextToken("=");
+ maxStepHeight = string::convert<float>(tok.nextToken());
+ }
+ else if (token == "maxBarrierHeight")
+ {
+ tok.assertNextToken("=");
+ maxBarrierHeight = string::convert<float>(tok.nextToken());
+ }
+ else if (token == "maxWaterJumpHeight")
+ {
+ tok.assertNextToken("=");
+ maxWaterJumpHeight = string::convert<float>(tok.nextToken());
+ }
+ else if (token == "maxFallHeight")
+ {
+ tok.assertNextToken("=");
+ maxFallHeight = string::convert<float>(tok.nextToken());
+ }
+ else if (token == "minFloorCos")
+ {
+ tok.assertNextToken("=");
+ minFloorCos = string::convert<float>(tok.nextToken());
+ }
+ else if (token == "tt_barrierJump")
+ {
+ tok.assertNextToken("=");
+ tt_barrierJump = string::convert<int>(tok.nextToken());
+ }
+ else if (token == "tt_startCrouching")
+ {
+ tok.assertNextToken("=");
+ tt_startCrouching = string::convert<int>(tok.nextToken());
+ }
+ else if (token == "tt_waterJump")
+ {
+ tok.assertNextToken("=");
+ tt_waterJump = string::convert<int>(tok.nextToken());
+ }
+ else if (token == "tt_startWalkOffLedge")
+ {
+ tok.assertNextToken("=");
+ tt_startWalkOffLedge = string::convert<int>(tok.nextToken());
+ }
+ else
+ {
+ throw parser::ParseException("Unknown settings token: " + token);
+ }
+ }
+}
+
+}
diff --git a/plugins/mapdoom3/aas/Doom3AasFileSettings.h b/plugins/mapdoom3/aas/Doom3AasFileSettings.h
new file mode 100644
index 0000000..d94ce98
--- /dev/null
+++ b/plugins/mapdoom3/aas/Doom3AasFileSettings.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "math/AABB.h"
+#include "math/Vector3.h"
+#include "parser/DefTokeniser.h"
+
+namespace map
+{
+
+#define MAX_AAS_BOUNDING_BOXES 4
+
+class Doom3AasFileSettings
+{
+public:
+ Doom3AasFileSettings();
+
+ int numBoundingBoxes;
+ AABB boundingBoxes[MAX_AAS_BOUNDING_BOXES];
+ bool usePatches;
+ bool writeBrushMap;
+ bool playerFlood;
+ bool noOptimize;
+ bool allowSwimReachabilities;
+ bool allowFlyReachabilities;
+ std::string fileExtension;
+ // physics settings
+ Vector3 gravity;
+ Vector3 gravityDir;
+ Vector3 invGravityDir;
+ float gravityValue;
+ float maxStepHeight;
+ float maxBarrierHeight;
+ float maxWaterJumpHeight;
+ float maxFallHeight;
+ float minFloorCos;
+
+ // fixed travel times
+ int tt_barrierJump;
+ int tt_startCrouching;
+ int tt_waterJump;
+ int tt_startWalkOffLedge;
+
+ // Parse from token stream. The opening "settings" token should already have been consumed
+ void parseFromTokens(parser::DefTokeniser& tok);
+};
+
+}
diff --git a/plugins/mapdoom3/aas/Util.h b/plugins/mapdoom3/aas/Util.h
new file mode 100644
index 0000000..1ca69d1
--- /dev/null
+++ b/plugins/mapdoom3/aas/Util.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "math/Vector3.h"
+#include "parser/DefTokeniser.h"
+#include "string/convert.h"
+
+namespace map
+{
+ inline Vector3 parseVector3(parser::DefTokeniser& tok)
+ {
+ Vector3 vec;
+
+ tok.assertNextToken("(");
+ vec[0] = string::convert<Vector3::ElementType>(tok.nextToken());
+ vec[1] = string::convert<Vector3::ElementType>(tok.nextToken());
+ vec[2] = string::convert<Vector3::ElementType>(tok.nextToken());
+ tok.assertNextToken(")");
+
+ return vec;
+ }
+}
diff --git a/plugins/mapdoom3/compiler/DebugRenderer.h b/plugins/mapdoom3/compiler/DebugRenderer.h
index e63fb43..478ae9c 100644
--- a/plugins/mapdoom3/compiler/DebugRenderer.h
+++ b/plugins/mapdoom3/compiler/DebugRenderer.h
@@ -96,7 +96,7 @@ public:
{}
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override
{
if (!_procFile) return;
@@ -118,17 +118,17 @@ public:
collector.addRenderable(*this, Matrix4::getIdentity());
}
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override
{
renderSolid(collector, volume);
}
- void setRenderSystem(const RenderSystemPtr& renderSystem)
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override
{}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
void setActiveNode(int nodeId)
diff --git a/plugins/mapdoom3/compiler/Doom3MapCompiler.cpp b/plugins/mapdoom3/compiler/Doom3MapCompiler.cpp
index e417443..861b3ee 100644
--- a/plugins/mapdoom3/compiler/Doom3MapCompiler.cpp
+++ b/plugins/mapdoom3/compiler/Doom3MapCompiler.cpp
@@ -8,6 +8,7 @@
#include <functional>
#include <boost/format.hpp>
+#include <boost/filesystem.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "os/path.h"
@@ -36,10 +37,10 @@ namespace map
}
// Renderable implementation (empty)
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override
{}
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override
{}
const AABB& localAABB() const
@@ -47,9 +48,9 @@ namespace map
return _emptyAABB;
}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
};
@@ -109,7 +110,7 @@ void Doom3MapCompiler::runDmap(const scene::INodePtr& root)
void Doom3MapCompiler::runDmap(const std::string& mapFile)
{
- if (!os::fileOrDirExists(mapFile) || file_is_directory(mapFile.c_str()))
+ if (!os::fileOrDirExists(mapFile) || boost::filesystem::is_directory(mapFile))
{
rError() << "Can't dmap, file doesn't exist: " << mapFile << std::endl;
return;
diff --git a/plugins/mapdoom3/compiler/OptIsland.cpp b/plugins/mapdoom3/compiler/OptIsland.cpp
index 680488a..3a7b11d 100644
--- a/plugins/mapdoom3/compiler/OptIsland.cpp
+++ b/plugins/mapdoom3/compiler/OptIsland.cpp
@@ -677,7 +677,7 @@ void OptIsland::removeIfColinear(OptVertex* ov)
// see if they are colinear
Vector3 dir1 = v3->v.vertex - v1->v.vertex;
- float len = dir1.normalise();
+ dir1.normalise();
Vector3 dir2 = v2->v.vertex - v1->v.vertex;
diff --git a/plugins/mapdoom3/compiler/ProcCompiler.cpp b/plugins/mapdoom3/compiler/ProcCompiler.cpp
index ed0270c..2b1dc72 100644
--- a/plugins/mapdoom3/compiler/ProcCompiler.cpp
+++ b/plugins/mapdoom3/compiler/ProcCompiler.cpp
@@ -159,7 +159,7 @@ public:
ProcPatch surface(*patch);
- if (patch->subdivionsFixed())
+ if (patch->subdivisionsFixed())
{
surface.subdivideExplicit(patch->getSubdivisions(), true);
}
@@ -326,8 +326,6 @@ private:
_buildBrush.contentShader = firstSide.material;
- bool mixed = false;
-
// a brush is only opaque if all sides are opaque
_buildBrush.opaque = true;
@@ -344,7 +342,6 @@ private:
if (flags != contents)
{
- mixed = true;
contents |= flags;
}
@@ -4503,7 +4500,7 @@ Surface ProcCompiler::createShadowVolume(const Matrix4& transform, const Surface
bool overflowed = false;
_indexFrustumNumber = 0;
int capPlaneBits = 0;
- bool callOptimizer = (optimize == SG_OFFLINE);
+ //bool callOptimizer = (optimize == SG_OFFLINE);
// the facing information will be the same for all six projections
// from a point light, as well as for any directed lights
diff --git a/plugins/mapdoom3/compiler/ProcPatch.cpp b/plugins/mapdoom3/compiler/ProcPatch.cpp
index 26cd33e..bb017e0 100644
--- a/plugins/mapdoom3/compiler/ProcPatch.cpp
+++ b/plugins/mapdoom3/compiler/ProcPatch.cpp
@@ -656,7 +656,6 @@ void ProcPatch::generateNormals()
{
for (int j = 0; j < _height; ++j)
{
- std::size_t count = 0;
const Vector3& base = _vertices[j * _width + i].vertex;
for (std::size_t k = 0; k < 8; ++k)
@@ -730,13 +729,6 @@ void ProcPatch::generateNormals()
}
sum += norm;
- count++;
- }
-
- if (count == 0)
- {
- //idLib::common->Printf("bad normal\n");
- count = 1;
}
_vertices[j * _width + i].normal = sum;
diff --git a/plugins/mapdoom3/mapdoom3.cpp b/plugins/mapdoom3/mapdoom3.cpp
index 6c4e421..20537c1 100644
--- a/plugins/mapdoom3/mapdoom3.cpp
+++ b/plugins/mapdoom3/mapdoom3.cpp
@@ -3,6 +3,7 @@
#include "Quake4MapFormat.h"
#include "Quake3MapFormat.h"
#include "compiler/Doom3MapCompiler.h"
+#include "aas/Doom3AasFileLoader.h"
#include "imapformat.h"
#include "itextstream.h"
@@ -10,12 +11,13 @@
extern "C" void DARKRADIANT_DLLEXPORT RegisterModule(IModuleRegistry& registry)
{
- registry.registerModule(map::Doom3MapFormatPtr(new map::Doom3MapFormat));
- registry.registerModule(map::Quake4MapFormatPtr(new map::Quake4MapFormat));
- registry.registerModule(map::Doom3PrefabFormatPtr(new map::Doom3PrefabFormat));
- registry.registerModule(map::Doom3MapCompilerPtr(new map::Doom3MapCompiler));
- registry.registerModule(map::Quake3MapFormatPtr(new map::Quake3MapFormat));
-
+ registry.registerModule(std::make_shared<map::Doom3MapFormat>());
+ registry.registerModule(std::make_shared<map::Quake4MapFormat>());
+ registry.registerModule(std::make_shared<map::Doom3PrefabFormat>());
+ registry.registerModule(std::make_shared<map::Doom3MapCompiler>());
+ registry.registerModule(std::make_shared<map::Quake3MapFormat>());
+ registry.registerModule(std::make_shared<map::Doom3AasFileLoader>());
+
// Initialise the streams using the given application context
module::initialiseStreams(registry.getApplicationContext());
diff --git a/plugins/mapdoom3/primitivewriters/PatchDefExporter.h b/plugins/mapdoom3/primitivewriters/PatchDefExporter.h
index 0b34975..ba26477 100644
--- a/plugins/mapdoom3/primitivewriters/PatchDefExporter.h
+++ b/plugins/mapdoom3/primitivewriters/PatchDefExporter.h
@@ -38,7 +38,7 @@ public:
// Writes a patchDef2/3 definition from the given patch to the given stream
static void exportPatch(std::ostream& stream, const IPatch& patch)
{
- if (patch.subdivionsFixed())
+ if (patch.subdivisionsFixed())
{
exportPatchDef3(stream, patch);
}
@@ -87,7 +87,7 @@ private:
stream << patch.getWidth() << " ";
stream << patch.getHeight() << " ";
- assert(patch.subdivionsFixed());
+ assert(patch.subdivisionsFixed());
Subdivisions divisions = patch.getSubdivisions();
stream << divisions.x() << " ";
diff --git a/plugins/md5model/MD5ModelNode.h b/plugins/md5model/MD5ModelNode.h
index 879e7c1..c278e3d 100644
--- a/plugins/md5model/MD5ModelNode.h
+++ b/plugins/md5model/MD5ModelNode.h
@@ -59,13 +59,13 @@ public:
void clearLights();
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // models are never highlighted themselves
+ return Highlight::NoHighlight; // models are never highlighted themselves
}
// Returns the name of the currently active skin
diff --git a/plugins/md5model/MD5Skeleton.cpp b/plugins/md5model/MD5Skeleton.cpp
index d8fad10..16a7921 100644
--- a/plugins/md5model/MD5Skeleton.cpp
+++ b/plugins/md5model/MD5Skeleton.cpp
@@ -14,10 +14,10 @@ namespace
Quaternion qm;
// Calculate angle between them.
- float cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + qa.z() * qb.z();
+ double cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + qa.z() * qb.z();
// if qa=qb or qa=-qb then theta = 0 and we can return qa
- if (abs(cosHalfTheta) > 1.0f)
+ if (abs(cosHalfTheta) > 1.0)
{
return qb;
}
@@ -27,7 +27,7 @@ namespace
// in a single frame - use this to rectify that.
Quaternion temp;
- if (cosHalfTheta < 0.0f)
+ if (cosHalfTheta < 0.0)
{
temp = qb*(-1);
cosHalfTheta = -cosHalfTheta;
@@ -38,12 +38,12 @@ namespace
}
// Calculate temporary values.
- float halfTheta = acos(cosHalfTheta);
- float sinHalfTheta = sqrt(1.0f - cosHalfTheta*cosHalfTheta);
+ double halfTheta = acos(cosHalfTheta);
+ double sinHalfTheta = sqrt(1.0 - cosHalfTheta*cosHalfTheta);
// if theta = 180 degrees then result is not fully defined
// we could rotate around any axis normal to qa or qb
- if (fabs(sinHalfTheta) < 0.006f)
+ if (fabs(sinHalfTheta) < 0.006)
{
qm.w() = (qa.w() * (1-fraction) + temp.w() * fraction);
qm.x() = (qa.x() * (1-fraction) + temp.x() * fraction);
@@ -52,8 +52,8 @@ namespace
return qm;
}
- float ratioA = sin((1 - fraction) * halfTheta) / sinHalfTheta;
- float ratioB = sin(fraction * halfTheta) / sinHalfTheta;
+ double ratioA = sin((1 - fraction) * halfTheta) / sinHalfTheta;
+ double ratioB = sin(fraction * halfTheta) / sinHalfTheta;
//calculate Quaternion.
qm.w() = (qa.w() * ratioA + temp.w() * ratioB);
diff --git a/plugins/model/PicoModelNode.h b/plugins/model/PicoModelNode.h
index faa9566..b8e41d6 100644
--- a/plugins/model/PicoModelNode.h
+++ b/plugins/model/PicoModelNode.h
@@ -78,13 +78,13 @@ public:
void clearLights();
// Renderable implementation
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // models are never highlighted themselves
+ return Highlight::NoHighlight; // models are never highlighted themselves
}
// Traceable implementation
diff --git a/plugins/particles/ParticleDef.cpp b/plugins/particles/ParticleDef.cpp
index 68152ec..a9df49e 100644
--- a/plugins/particles/ParticleDef.cpp
+++ b/plugins/particles/ParticleDef.cpp
@@ -59,6 +59,9 @@ void ParticleDef::copyFrom(const IParticleDef& other)
stage->signal_changed().connect(_changedSignal.make_slot());
_stages.push_back(stage);
}
+
+ // We've changed all the stages, so emit the changed signal now (#4411)
+ _changedSignal.emit();
}
void ParticleDef::parseFromTokens(parser::DefTokeniser& tok)
diff --git a/plugins/particles/ParticleDef.h b/plugins/particles/ParticleDef.h
index 135beee..6d81dc5 100644
--- a/plugins/particles/ParticleDef.h
+++ b/plugins/particles/ParticleDef.h
@@ -47,12 +47,12 @@ public:
/**
* Return the ParticleDef name.
*/
- const std::string& getName() const
+ const std::string& getName() const override
{
return _name;
}
- const std::string& getFilename() const
+ const std::string& getFilename() const override
{
return _filename;
}
@@ -71,42 +71,45 @@ public:
}
// IParticleDef implementation
- sigc::signal<void> signal_changed() const { return _changedSignal; }
+ sigc::signal<void> signal_changed() const override
+ {
+ return _changedSignal;
+ }
- float getDepthHack() const
+ float getDepthHack() const override
{
return _depthHack;
}
- void setDepthHack(float value)
+ void setDepthHack(float value) override
{
_depthHack = value;
}
- std::size_t getNumStages() const
+ std::size_t getNumStages() const override
{
return _stages.size();
}
- const IStageDef& getStage(std::size_t stageNum) const
+ const IStageDef& getStage(std::size_t stageNum) const override
{
return *_stages[stageNum];
}
- IStageDef& getStage(std::size_t stageNum)
+ IStageDef& getStage(std::size_t stageNum) override
{
return *_stages[stageNum];
}
- std::size_t addParticleStage() ;
+ std::size_t addParticleStage() override;
- void removeParticleStage(std::size_t index);
+ void removeParticleStage(std::size_t index) override;
- void swapParticleStages(std::size_t index, std::size_t index2);
+ void swapParticleStages(std::size_t index, std::size_t index2) override;
void appendStage(const StageDefPtr& stage);
- bool operator==(const IParticleDef& other) const
+ bool operator==(const IParticleDef& other) const override
{
// Compare depth hack flag
if (getDepthHack() != other.getDepthHack()) return false;
@@ -124,12 +127,12 @@ public:
return true;
}
- bool operator!=(const IParticleDef& other) const
+ bool operator!=(const IParticleDef& other) const override
{
return !operator==(other);
}
- void copyFrom(const IParticleDef& other);
+ void copyFrom(const IParticleDef& other) override;
void parseFromTokens(parser::DefTokeniser& tok);
diff --git a/plugins/particles/ParticleNode.cpp b/plugins/particles/ParticleNode.cpp
index 3975069..46f055d 100644
--- a/plugins/particles/ParticleNode.cpp
+++ b/plugins/particles/ParticleNode.cpp
@@ -31,9 +31,9 @@ const AABB& ParticleNode::localAABB() const
return _renderableParticle->getBounds();
}
-bool ParticleNode::isHighlighted(void) const
+std::size_t ParticleNode::getHighlightFlags()
{
- return false;
+ return Highlight::NoHighlight;
}
const Matrix4& ParticleNode::localToParent() const
diff --git a/plugins/particles/ParticleNode.h b/plugins/particles/ParticleNode.h
index e8ebd7d..a3680e9 100644
--- a/plugins/particles/ParticleNode.h
+++ b/plugins/particles/ParticleNode.h
@@ -33,12 +33,12 @@ public:
IRenderableParticlePtr getParticle() const;
const AABB& localAABB() const;
- bool isHighlighted(void) const;
+ std::size_t getHighlightFlags() override;
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
// ITransformNode
const Matrix4& localToParent() const;
diff --git a/plugins/particles/ParticleQuad.h b/plugins/particles/ParticleQuad.h
index cc5742d..eb7f157 100644
--- a/plugins/particles/ParticleQuad.h
+++ b/plugins/particles/ParticleQuad.h
@@ -55,7 +55,7 @@ struct ParticleQuad
*
* [Optional]: s0 and sWidth are used for particle animation frames.
*
- * @aspect: scales the horizontal coords by this factor.
+ * @aspect: scales the vertical size of the quad by this factor.
* @s0: defines the horizontal frame start coordinate in texture space (s).
* @sWidth: defines the width of this frame in texture space.
*/
@@ -71,10 +71,10 @@ struct ParticleQuad
0, 0, 1, 0,
0, 0, 0, 1);
- verts[0] = Vertex(rotation.transformPoint(Vector3(-size*aspect, +size, 0)), Vector2(s0,t0), colour, normal);
- verts[1] = Vertex(rotation.transformPoint(Vector3(+size*aspect, +size, 0)), Vector2(s0 + sWidth,t0), colour, normal);
- verts[2] = Vertex(rotation.transformPoint(Vector3(+size*aspect, -size, 0)), Vector2(s0 + sWidth,t0 + tWidth), colour, normal);
- verts[3] = Vertex(rotation.transformPoint(Vector3(-size*aspect, -size, 0)), Vector2(s0,t0 + tWidth), colour, normal);
+ verts[0] = Vertex(rotation.transformPoint(Vector3(-size, +size*aspect, 0)), Vector2(s0, t0), colour, normal);
+ verts[1] = Vertex(rotation.transformPoint(Vector3(+size, +size*aspect, 0)), Vector2(s0 + sWidth, t0), colour, normal);
+ verts[2] = Vertex(rotation.transformPoint(Vector3(+size, -size*aspect, 0)), Vector2(s0 + sWidth, t0 + tWidth), colour, normal);
+ verts[3] = Vertex(rotation.transformPoint(Vector3(-size, -size*aspect, 0)), Vector2(s0,t0 + tWidth), colour, normal);
}
void translate(const Vector3& offset)
diff --git a/plugins/particles/ParticlesManager.cpp b/plugins/particles/ParticlesManager.cpp
index e9f26b5..fca77a9 100644
--- a/plugins/particles/ParticlesManager.cpp
+++ b/plugins/particles/ParticlesManager.cpp
@@ -290,20 +290,29 @@ void ParticlesManager::saveParticleDef(const std::string& particleName)
std::string relativePath = PARTICLES_DIR + particle->getFilename();
- fs::path particlesModPath = GlobalGameManager().getModPath();
- particlesModPath /= PARTICLES_DIR;
+ fs::path targetPath = GlobalGameManager().getModPath();
+
+ if (targetPath.empty())
+ {
+ targetPath = GlobalGameManager().getUserEnginePath();
+
+ rMessage() << "No mod base path found, falling back to user engine path to save particle file: " <<
+ targetPath.string() << std::endl;
+ }
+
+ targetPath /= PARTICLES_DIR;
// Ensure the particles folder exists
- fs::create_directories(particlesModPath);
+ fs::create_directories(targetPath);
- fs::path targetFile = particlesModPath / particle->getFilename();
+ fs::path targetFile = targetPath / particle->getFilename();
// If the file doesn't exist yet, let's check if we need to inherit stuff first from the VFS
if (!fs::exists(targetFile))
{
ArchiveTextFilePtr inheritFile = GlobalFileSystem().openTextFile(relativePath);
- if (inheritFile != NULL)
+ if (inheritFile)
{
// There is a file with that name already in the VFS, copy it to the target file
TextInputStream& inheritStream = inheritFile->getInputStream();
diff --git a/plugins/particles/RenderableParticle.h b/plugins/particles/RenderableParticle.h
index b3d868c..6c73280 100644
--- a/plugins/particles/RenderableParticle.h
+++ b/plugins/particles/RenderableParticle.h
@@ -64,19 +64,19 @@ public:
void update(const Matrix4& viewRotation);
// Front-end render methods
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
void renderSolid(RenderableCollector& collector, const VolumeTest& volume,
const Matrix4& localToWorld, const IRenderEntity* entity) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
void renderWireframe(RenderableCollector& collector, const VolumeTest& volume,
const Matrix4& localToWorld, const IRenderEntity* entity) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
const IParticleDefPtr& getParticleDef() const;
diff --git a/plugins/particles/RenderableParticleBunch.cpp b/plugins/particles/RenderableParticleBunch.cpp
index d5bc34f..ac97da1 100644
--- a/plugins/particles/RenderableParticleBunch.cpp
+++ b/plugins/particles/RenderableParticleBunch.cpp
@@ -197,7 +197,7 @@ Matrix4 RenderableParticleBunch::getAimedMatrix(const Vector3& particleVelocity)
Vector3 z = object2Vel.z().getVector3();
// The particle needs to be rotated by this angle around the velocity axis
- float aimedAngle = z.angle(-viewProj);
+ double aimedAngle = z.angle(-viewProj);
// Use the cross to check whether to rotate in negative or positive direction
if (z.crossProduct(-viewProj).dot(vel) > 0)
@@ -609,8 +609,7 @@ void RenderableParticleBunch::pushAimedParticles(ParticleRenderInfo& particle, s
float height = static_cast<float>(velocity.getLength());
- aimedParticle.aspect = 2 * aimedParticle.size / height;
- aimedParticle.size = height * 0.5f;
+ aimedParticle.aspect = height / (2 * aimedParticle.size);
// Calculate the vertical texture coordinates
aimedParticle.tWidth = 1.0f / static_cast<float>(numQuads);
diff --git a/plugins/particles/StageDef.cpp b/plugins/particles/StageDef.cpp
index d6952a4..8a4d4fd 100644
--- a/plugins/particles/StageDef.cpp
+++ b/plugins/particles/StageDef.cpp
@@ -159,28 +159,28 @@ void StageDef::copyFrom(const IStageDef& other)
setOffset(other.getOffset());
setOrientationType(other.getOrientationType());
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
setOrientationParm(i, other.getOrientationParm(i));
}
setDistributionType(other.getDistributionType());
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
setDistributionParm(i, other.getDistributionParm(i));
}
setDirectionType(other.getDirectionType());
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
setDirectionParm(i, other.getDirectionParm(i));
}
setCustomPathType(other.getCustomPathType());
- for (int i = 0; i < 7; ++i)
+ for (int i = 0; i < 8; ++i)
{
setCustomPathParm(i, other.getCustomPathParm(i));
}
@@ -604,7 +604,8 @@ std::ostream& operator<<(std::ostream& stream, const StageDef& stage)
case StageDef::DISTRIBUTION_SPHERE:
stream << "sphere " << stage.getDistributionParm(0) << " "
<< stage.getDistributionParm(1) << " "
- << stage.getDistributionParm(2) << std::endl;
+ << stage.getDistributionParm(2) << " "
+ << stage.getDistributionParm(3) << std::endl;
break;
};
@@ -743,28 +744,28 @@ bool StageDef::operator==(const IStageDef& other) const
if (getOffset() != other.getOffset()) return false;
if (getOrientationType() != other.getOrientationType()) return false;
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
if (getOrientationParm(i) != other.getOrientationParm(i)) return false;
}
if (getDistributionType() != other.getDistributionType()) return false;
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
if (getDistributionParm(i) != other.getDistributionParm(i)) return false;
}
if (getDirectionType() != other.getDirectionType()) return false;
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 4; ++i)
{
if (getDirectionParm(i) != other.getDirectionParm(i)) return false;
}
if (getCustomPathType() != other.getCustomPathType()) return false;
- for (int i = 0; i < 7; ++i)
+ for (int i = 0; i < 8; ++i)
{
if (getCustomPathParm(i) != other.getCustomPathParm(i)) return false;
}
diff --git a/plugins/script/ScriptingSystem.cpp b/plugins/script/ScriptingSystem.cpp
index fb1b3ec..96e8f97 100644
--- a/plugins/script/ScriptingSystem.cpp
+++ b/plugins/script/ScriptingSystem.cpp
@@ -195,7 +195,7 @@ void ScriptingSystem::initialise()
page->page = new ScriptWindow(GlobalMainFrame().getWxTopLevelWindow());
page->tabIcon = "icon_script.png";
page->tabLabel = _("Script");
- page->insertBefore = "console";
+ page->position = IGroupDialog::Page::Position::Console - 10; // insert before console
GlobalGroupDialog().addPage(page);
}
diff --git a/plugins/script/interfaces/PatchInterface.cpp b/plugins/script/interfaces/PatchInterface.cpp
index 3eead2e..7fc27b1 100644
--- a/plugins/script/interfaces/PatchInterface.cpp
+++ b/plugins/script/interfaces/PatchInterface.cpp
@@ -168,12 +168,12 @@ public:
return patchNode->getPatch().hasVisibleMaterial();
}
- bool subdivionsFixed() const
+ bool subdivisionsFixed() const
{
IPatchNodePtr patchNode = std::dynamic_pointer_cast<IPatchNode>(_node.lock());
if (patchNode == NULL) return false;
- return patchNode->getPatch().subdivionsFixed();
+ return patchNode->getPatch().subdivisionsFixed();
}
Subdivisions getSubdivisions() const
@@ -274,7 +274,8 @@ void PatchInterface::registerInterface(boost::python::object& nspace) {
boost::python::return_value_policy<boost::python::copy_const_reference>())
.def("setShader", &ScriptPatchNode::setShader)
.def("hasVisibleMaterial", &ScriptPatchNode::hasVisibleMaterial)
- .def("subdivionsFixed", &ScriptPatchNode::subdivionsFixed)
+ .def("subdivionsFixed", &ScriptPatchNode::subdivisionsFixed) // typo used to be there in previous releases, leave it in there for compatibility reasons
+ .def("subdivisionsFixed", &ScriptPatchNode::subdivisionsFixed)
.def("getSubdivisions", &ScriptPatchNode::getSubdivisions)
.def("setFixedSubdivisions", &ScriptPatchNode::setFixedSubdivisions)
.def("controlPointsChanged", &ScriptPatchNode::controlPointsChanged)
diff --git a/plugins/script/interfaces/SceneGraphInterface.h b/plugins/script/interfaces/SceneGraphInterface.h
index eecb6e0..47de454 100644
--- a/plugins/script/interfaces/SceneGraphInterface.h
+++ b/plugins/script/interfaces/SceneGraphInterface.h
@@ -83,7 +83,7 @@ public:
scene::INodePtr node = _node.lock();
if (node == NULL) return false;
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
return (selectable != NULL) ? selectable->isSelected() : false;
}
@@ -92,21 +92,21 @@ public:
scene::INodePtr node = _node.lock();
if (node == NULL) return;
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
if (selectable != NULL) {
selectable->setSelected(selected);
}
}
- void invertSelected(bool selected) {
+ void invertSelected() {
scene::INodePtr node = _node.lock();
if (node == NULL) return;
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
if (selectable != NULL) {
- selectable->invertSelected();
+ selectable->setSelected(!selectable->isSelected());
}
}
};
diff --git a/plugins/shaders/Doom3ShaderSystem.cpp b/plugins/shaders/Doom3ShaderSystem.cpp
index 989ccbb..862a8fb 100644
--- a/plugins/shaders/Doom3ShaderSystem.cpp
+++ b/plugins/shaders/Doom3ShaderSystem.cpp
@@ -164,8 +164,10 @@ void Doom3ShaderSystem::refresh() {
}
// Is the shader system realised
-bool Doom3ShaderSystem::isRealised() {
- return _realised;
+bool Doom3ShaderSystem::isRealised()
+{
+ // Don't report true until we have at least some definitions loaded
+ return _realised && _library->getNumDefinitions() > 0;
}
// Return a shader by name
diff --git a/plugins/shaders/textures/TextureManipulator.cpp b/plugins/shaders/textures/TextureManipulator.cpp
index c9bc78a..2b98ce2 100644
--- a/plugins/shaders/textures/TextureManipulator.cpp
+++ b/plugins/shaders/textures/TextureManipulator.cpp
@@ -544,8 +544,9 @@ void TextureManipulator::mipReduce(byte *in, byte *out,
/* greebo: This gets called by the preference system and is responsible for adding the
* according pages and elements to the preference dialog.*/
-void TextureManipulator::constructPreferences() {
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage("Settings/Textures");
+void TextureManipulator::constructPreferences()
+{
+ IPreferencePage& page = GlobalPreferenceSystem().getPage("Settings/Textures");
// Create the string list containing the quality captions
std::list<std::string> percentages;
@@ -555,10 +556,10 @@ void TextureManipulator::constructPreferences() {
percentages.push_back("50%");
percentages.push_back("100%");
- page->appendCombo("Texture Quality", RKEY_TEXTURES_QUALITY, percentages);
+ page.appendCombo("Texture Quality", RKEY_TEXTURES_QUALITY, percentages);
// Texture Gamma Settings
- page->appendSpinner("Texture Gamma", RKEY_TEXTURES_GAMMA, 0.0f, 1.0f, 10);
+ page.appendSpinner("Texture Gamma", RKEY_TEXTURES_GAMMA, 0.0f, 1.0f, 10);
}
} // namespace shaders
diff --git a/plugins/sound/WavFileLoader.h b/plugins/sound/WavFileLoader.h
index a44b8ce..06a666e 100644
--- a/plugins/sound/WavFileLoader.h
+++ b/plugins/sound/WavFileLoader.h
@@ -87,36 +87,36 @@ public:
unsigned short bps = 0;
stream.read(reinterpret_cast<byte*>(&bps), 2);
- int bufferSize = 0;
+ //int bufferSize = 0;
if (channels == 1) {
if (bps == 8) {
format = AL_FORMAT_MONO8;
// Set BufferSize to 250ms (Frequency divided by 4 (quarter of a second))
- bufferSize = freq / 4;
+ //bufferSize = freq / 4;
}
else {
format = AL_FORMAT_MONO16;
// Set BufferSize to 250ms (Frequency * 2 (16bit) divided by 4 (quarter of a second))
- bufferSize = freq >> 1;
+ //bufferSize = freq >> 1;
// IMPORTANT : The Buffer Size must be an exact multiple of the BlockAlignment ...
- bufferSize -= (bufferSize % 2);
+ //bufferSize -= (bufferSize % 2);
}
}
else {
if (bps == 8) {
format = AL_FORMAT_STEREO16;
// Set BufferSize to 250ms (Frequency * 2 (8bit stereo) divided by 4 (quarter of a second))
- bufferSize = freq >> 1;
+ //bufferSize = freq >> 1;
// IMPORTANT : The Buffer Size must be an exact multiple of the BlockAlignment ...
- bufferSize -= (bufferSize % 2);
+ //bufferSize -= (bufferSize % 2);
}
else {
format = AL_FORMAT_STEREO16;
// Set BufferSize to 250ms (Frequency * 4 (16bit stereo) divided by 4 (quarter of a second))
- bufferSize = freq;
+ //bufferSize = freq;
// IMPORTANT : The Buffer Size must be an exact multiple of the BlockAlignment ...
- bufferSize -= (bufferSize % 4);
+ //bufferSize -= (bufferSize % 4);
}
}
diff --git a/plugins/uimanager/GroupDialog.cpp b/plugins/uimanager/GroupDialog.cpp
index e74871c..d618f79 100644
--- a/plugins/uimanager/GroupDialog.cpp
+++ b/plugins/uimanager/GroupDialog.cpp
@@ -107,12 +107,12 @@ std::string GroupDialog::getPageName()
wxWindow* curPage = getPage();
// Now cycle through the list of pages and find the matching one
- for (std::size_t i = 0; i < _pages.size(); i++)
+ for (Pages::value_type& i : _pages)
{
- if (_pages[i].page == curPage)
+ if (i.second.page == curPage)
{
// Found page. Set it to active if it is not already active.
- return _pages[i].name;
+ return i.second.name;
}
}
@@ -127,14 +127,14 @@ void GroupDialog::setPage(const std::string& name)
setPage(_pages[0].page);
// Now search for the correct page.
- for (std::size_t i = 0; i < _pages.size(); i++)
+ for (Pages::value_type& i : _pages)
{
- if (_pages[i].name == name)
+ if (i.second.name == name)
{
// Found page. Set it to active if it is not already active.
- if (_pages[i].page != NULL && getPage() != _pages[i].page)
+ if (i.second.page != nullptr && getPage() != i.second.page)
{
- setPage(_pages[i].page);
+ setPage(i.second.page);
}
// Show the window if the notebook is hosted here
@@ -151,7 +151,14 @@ void GroupDialog::setPage(const std::string& name)
void GroupDialog::setPage(wxWindow* page)
{
- _notebook->SetSelection(_notebook->FindPage(page));
+ if (page == nullptr) return;
+
+ int pageIndex = _notebook->FindPage(page);
+
+ if (pageIndex != wxNOT_FOUND)
+ {
+ _notebook->SetSelection(pageIndex);
+ }
}
void GroupDialog::togglePage(const std::string& name)
@@ -246,30 +253,36 @@ wxWindow* GroupDialog::addPage(const PagePtr& page)
int imageId = page->tabIcon.empty() ? -1 :
_imageList->Add(wxArtProvider::GetBitmap(LocalBitmapArtProvider::ArtIdPrefix() + page->tabIcon));
- // Create the notebook page
- size_t position = _notebook->GetPageCount();
- Pages::iterator insertIter = _pages.end();
+ // Handle position conflicts first
+ Pages::const_iterator conflictingPage = _pages.find(page->position);
- if (!page->insertBefore.empty())
+ // Move back one position until we find a free slot
+ while (conflictingPage != _pages.end())
{
- // Find the page with that name
- for (Pages::iterator i = _pages.begin(); i != _pages.end(); ++i)
- {
- // Skip the wrong ones
- if (i->name != page->insertBefore) continue;
+ page->position = conflictingPage->second.position + 1;
+ conflictingPage = _pages.find(page->position);
+ }
+
+ // Create the notebook page
+ size_t insertPosition = _notebook->GetPageCount();
+
+ // Find a page with a higher position value and sort the incoming one to the left
+ for (Pages::value_type existing : _pages)
+ {
+ if (page->position < existing.second.position)
+ {
// Found, extract the tab position and break the loop
- position = _notebook->FindPage(i->page);
- insertIter = i;
+ insertPosition = _notebook->FindPage(existing.second.page);
break;
}
}
page->page->Reparent(_notebook.get());
- _notebook->InsertPage(position, page->page, page->tabLabel, false, imageId);
+ _notebook->InsertPage(insertPosition, page->page, page->tabLabel, false, imageId);
// Add this page by copy to the local list
- _pages.insert(insertIter, Page(*page));
+ _pages.insert(std::make_pair(page->position, Page(*page)));
return page->page;
}
@@ -280,10 +293,10 @@ void GroupDialog::removePage(const std::string& name)
for (Pages::iterator i = _pages.begin(); i != _pages.end(); ++i)
{
// Skip the wrong ones
- if (i->name != name) continue;
+ if (i->second.name != name) continue;
// Remove the page from the notebook
- _notebook->DeletePage(_notebook->FindPage(i->page));
+ _notebook->DeletePage(_notebook->FindPage(i->second.page));
// Remove the page and break the loop, iterators are invalid
_pages.erase(i);
diff --git a/plugins/uimanager/GroupDialog.h b/plugins/uimanager/GroupDialog.h
index f0079f0..44b480e 100644
--- a/plugins/uimanager/GroupDialog.h
+++ b/plugins/uimanager/GroupDialog.h
@@ -1,6 +1,7 @@
#pragma once
#include <memory>
+#include <map>
#include "iradiant.h"
#include "igroupdialog.h"
#include "wxutil/window/TransientWindow.h"
@@ -35,7 +36,8 @@ class GroupDialog :
public IGroupDialog
{
private:
- typedef std::vector<Page> Pages;
+ // Pages, sorted by position
+ typedef std::map<int, Page> Pages;
// The actual list instance
Pages _pages;
diff --git a/plugins/uimanager/Makefile.am b/plugins/uimanager/Makefile.am
index b625ca8..73ecaf5 100644
--- a/plugins/uimanager/Makefile.am
+++ b/plugins/uimanager/Makefile.am
@@ -7,6 +7,8 @@ modules_LTLIBRARIES = uimanager.la
uimanager_la_LDFLAGS = -module -avoid-version \
$(WX_LIBS) \
$(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(GLEW_LIBS) \
$(GL_LIBS)
uimanager_la_LIBADD = $(top_builddir)/libs/wxutil/libwxutil.la \
diff --git a/plugins/uimanager/Makefile.in b/plugins/uimanager/Makefile.in
index d48eecf..54d1196 100644
--- a/plugins/uimanager/Makefile.in
+++ b/plugins/uimanager/Makefile.in
@@ -412,6 +412,8 @@ modules_LTLIBRARIES = uimanager.la
uimanager_la_LDFLAGS = -module -avoid-version \
$(WX_LIBS) \
$(XML_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
$(GLEW_LIBS) \
$(GL_LIBS)
diff --git a/plugins/uimanager/MenuManager.cpp b/plugins/uimanager/MenuManager.cpp
index 7bb34f0..524cd57 100644
--- a/plugins/uimanager/MenuManager.cpp
+++ b/plugins/uimanager/MenuManager.cpp
@@ -378,7 +378,7 @@ void MenuManager::remove(const std::string& path)
else if (parent->getType() == menuBar)
{
wxMenuBar* parentBar = static_cast<wxMenuBar*>(parent->getWidget());
- wxMenu* menu = static_cast<wxMenu*>(item->getWidget());
+ static_cast<wxMenu*>(item->getWidget());
int oldPosition = parent->getMenuPosition(item);
@@ -388,7 +388,7 @@ void MenuManager::remove(const std::string& path)
item->removeAllChildren();
item->setWidget(NULL);
- menu = parentBar->Remove(oldPosition);
+ wxMenu* menu = parentBar->Remove(oldPosition);
delete menu;
}
else
diff --git a/plugins/uimanager/StatusBarManager.cpp b/plugins/uimanager/StatusBarManager.cpp
index d0932a1..6d9cdaa 100644
--- a/plugins/uimanager/StatusBarManager.cpp
+++ b/plugins/uimanager/StatusBarManager.cpp
@@ -57,7 +57,8 @@ wxWindow* StatusBarManager::getElement(const std::string& name)
return (found != _elements.end()) ? found->second->toplevel : NULL;
}
-void StatusBarManager::addTextElement(const std::string& name, const std::string& icon, int pos)
+void StatusBarManager::addTextElement(const std::string& name, const std::string& icon,
+ int pos, const std::string& description)
{
// Get a free position
int freePos = getFreePosition(pos);
@@ -66,6 +67,11 @@ void StatusBarManager::addTextElement(const std::string& name, const std::string
textPanel->SetSizer(new wxBoxSizer(wxHORIZONTAL));
textPanel->SetName("Statusbarconainer " + name);
+ if (!description.empty())
+ {
+ textPanel->SetToolTip(description);
+ }
+
if (!icon.empty())
{
wxStaticBitmap* img = new wxStaticBitmap(textPanel, wxID_ANY,
@@ -76,6 +82,11 @@ void StatusBarManager::addTextElement(const std::string& name, const std::string
wxStaticText* label = new wxStaticText(textPanel, wxID_ANY, "");
textPanel->GetSizer()->Add(label, 1, wxEXPAND | wxALL, 1);
+ if (!description.empty())
+ {
+ label->SetToolTip(description);
+ }
+
StatusBarElementPtr element(new StatusBarElement(textPanel, label));
// Store this element
diff --git a/plugins/uimanager/StatusBarManager.h b/plugins/uimanager/StatusBarManager.h
index fa907d0..a3cc571 100644
--- a/plugins/uimanager/StatusBarManager.h
+++ b/plugins/uimanager/StatusBarManager.h
@@ -59,7 +59,7 @@ public:
/**
* Get the status bar widget, for packing into the main window.
*/
- wxWindow* getStatusBar();
+ wxWindow* getStatusBar() override;
/**
* greebo: This adds a named element to the status bar. Pass the widget
@@ -70,14 +70,14 @@ public:
* @pos: the position to insert. Use POS_FRONT or POS_BACK to put the element
* at the front or back of the status bar container.
*/
- void addElement(const std::string& name, wxWindow* widget, int pos);
+ void addElement(const std::string& name, wxWindow* widget, int pos) override;
/**
* Returns a named status bar widget, previously added by addElement().
*
* @returns: NULL if the named widget does not exist.
*/
- wxWindow* getElement(const std::string& name);
+ wxWindow* getElement(const std::string& name) override;
/**
* greebo: A specialised method, adding a named text element.
@@ -89,19 +89,20 @@ public:
* @pos: the position to insert. Use POS_FRONT or POS_BACK to put the element
* at the front or back of the status bar container.
*/
- void addTextElement(const std::string& name, const std::string& icon, int pos);
+ void addTextElement(const std::string& name, const std::string& icon, int pos,
+ const std::string& description) override;
/**
* Updates the content of the named text element. The name must refer to
* an element previously added by addTextElement().
*/
- void setText(const std::string& name, const std::string& text, bool immediateUpdate);
+ void setText(const std::string& name, const std::string& text, bool immediateUpdate) override;
void onRadiantShutdown();
protected:
// Gets called when the app is idle - this fills in the status text
- void onIdle();
+ void onIdle() override;
private:
// Returns an integer position which is not used yet.
diff --git a/plugins/uimanager/ToolbarManager.cpp b/plugins/uimanager/ToolbarManager.cpp
index b572ca3..2a00a9b 100644
--- a/plugins/uimanager/ToolbarManager.cpp
+++ b/plugins/uimanager/ToolbarManager.cpp
@@ -76,7 +76,7 @@ wxToolBarToolBase* ToolbarManager::createToolItem(wxToolBar* toolbar, xml::Node&
if (nodeName == "toolbutton")
{
// Create a new ToolButton and assign the right callback
- toolItem = toolbar->AddTool(_nextToolItemId++,
+ toolItem = toolbar->AddTool(_nextToolItemId++, name,
wxArtProvider::GetBitmap(LocalBitmapArtProvider::ArtIdPrefix() + icon),
tooltip);
}
diff --git a/plugins/uimanager/UIManager.cpp b/plugins/uimanager/UIManager.cpp
index dcea218..26b5900 100644
--- a/plugins/uimanager/UIManager.cpp
+++ b/plugins/uimanager/UIManager.cpp
@@ -1,5 +1,6 @@
#include "UIManager.h"
+#include "i18n.h"
#include "itextstream.h"
#include "iregistry.h"
#include "iradiant.h"
@@ -110,7 +111,8 @@ void UIManager::initialiseModule(const ApplicationContext& ctx)
_statusBarManager.addTextElement(
STATUSBAR_COMMAND,
"", // no icon
- IStatusBarManager::POS_COMMAND
+ IStatusBarManager::POS_COMMAND,
+ _("Describes available Mouse Commands")
);
wxFileSystem::AddHandler(new wxLocalFSHandler);
diff --git a/plugins/undo/UndoSystem.cpp b/plugins/undo/UndoSystem.cpp
index 49e5939..bae5374 100644
--- a/plugins/undo/UndoSystem.cpp
+++ b/plugins/undo/UndoSystem.cpp
@@ -8,6 +8,7 @@
#include "ieventmanager.h"
#include "ipreferencesystem.h"
#include "iscenegraph.h"
+#include "imap.h"
#include <iostream>
#include <map>
@@ -254,6 +255,7 @@ public:
_dependencies.insert(MODULE_COMMANDSYSTEM);
_dependencies.insert(MODULE_SCENEGRAPH);
_dependencies.insert(MODULE_EVENTMANAGER);
+ _dependencies.insert(MODULE_MAP);
}
return _dependencies;
@@ -280,6 +282,10 @@ public:
// add the preference settings
constructPreferences();
+
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &RadiantUndoSystem::onMapEvent)
+ );
}
// This is connected to the CommandSystem
@@ -295,6 +301,14 @@ public:
}
private:
+ void onMapEvent(IMap::MapEvent ev)
+ {
+ if (ev == IMap::MapUnloaded)
+ {
+ clear();
+ }
+ }
+
// Sets the size of the undoStack
void setLevels(std::size_t levels)
{
@@ -381,8 +395,8 @@ private:
// Gets called by the PreferenceSystem as request to create the according settings page
void constructPreferences()
{
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Undo System"));
- page->appendSpinner(_("Undo Queue Size"), RKEY_UNDO_QUEUE_SIZE, 0, 1024, 1);
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Undo System"));
+ page.appendSpinner(_("Undo Queue Size"), RKEY_UNDO_QUEUE_SIZE, 0, 1024, 1);
}
}; // class RadiantUndoSystem
diff --git a/plugins/xmlregistry/Makefile.am b/plugins/xmlregistry/Makefile.am
index 8ba5726..7da2f2c 100644
--- a/plugins/xmlregistry/Makefile.am
+++ b/plugins/xmlregistry/Makefile.am
@@ -7,6 +7,10 @@ modules_LTLIBRARIES = xmlregistry.la
xmlregistry_la_LIBADD = $(top_builddir)/libs/xmlutil/libxmlutil.la
xmlregistry_la_LDFLAGS = -module -avoid-version \
- $(XML_LIBS) $(WX_LIBS) $(LIBSIGC_LIBS)
+ $(XML_LIBS) \
+ $(WX_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(LIBSIGC_LIBS)
xmlregistry_la_SOURCES = RegistryTree.cpp XMLRegistry.cpp XMLRegistryModule.cpp
diff --git a/plugins/xmlregistry/Makefile.in b/plugins/xmlregistry/Makefile.in
index 093ca9f..4fe36bf 100644
--- a/plugins/xmlregistry/Makefile.in
+++ b/plugins/xmlregistry/Makefile.in
@@ -407,7 +407,11 @@ modulesdir = $(pkglibdir)/modules
modules_LTLIBRARIES = xmlregistry.la
xmlregistry_la_LIBADD = $(top_builddir)/libs/xmlutil/libxmlutil.la
xmlregistry_la_LDFLAGS = -module -avoid-version \
- $(XML_LIBS) $(WX_LIBS) $(LIBSIGC_LIBS)
+ $(XML_LIBS) \
+ $(WX_LIBS) \
+ $(BOOST_FILESYSTEM_LIBS) \
+ $(BOOST_SYSTEM_LIBS) \
+ $(LIBSIGC_LIBS)
xmlregistry_la_SOURCES = RegistryTree.cpp XMLRegistry.cpp XMLRegistryModule.cpp
all: all-am
diff --git a/radiant/Makefile.am b/radiant/Makefile.am
index 64b3bb6..612cb77 100644
--- a/radiant/Makefile.am
+++ b/radiant/Makefile.am
@@ -120,6 +120,7 @@ darkradiant_SOURCES = main.cpp \
ui/menu/FiltersMenu.cpp \
ui/prefdialog/PrefPage.cpp \
ui/prefdialog/PrefDialog.cpp \
+ ui/prefdialog/PreferenceItem.cpp \
ui/transform/TransformDialog.cpp \
ui/modelselector/MaterialsList.cpp \
ui/modelselector/ModelSelector.cpp \
@@ -146,6 +147,8 @@ darkradiant_SOURCES = main.cpp \
ui/mousetool/ToolMappingDialog.cpp \
ui/animationpreview/AnimationPreview.cpp \
ui/animationpreview/MD5AnimationViewer.cpp \
+ ui/aas/AasControl.cpp \
+ ui/aas/AasControlDialog.cpp \
xyview/tools/BrushCreatorTool.cpp \
xyview/tools/ClipperTool.cpp \
xyview/XYWnd.cpp \
@@ -158,6 +161,7 @@ darkradiant_SOURCES = main.cpp \
textool/item/PatchItem.cpp \
textool/item/PatchVertexItem.cpp \
textool/TexTool.cpp \
+ layers/LayerInfoFileModule.cpp \
layers/LayerCommandTarget.cpp \
layers/LayerSystem.cpp \
modulesystem/DynamicLibrary.cpp \
@@ -172,6 +176,7 @@ darkradiant_SOURCES = main.cpp \
selection/shaderclipboard/ClosestTexturableFinder.cpp \
selection/selectionset/SelectionSetManager.cpp \
selection/selectionset/SelectionSetToolmenu.cpp \
+ selection/selectionset/SelectionSetInfoFileModule.cpp \
selection/selectionset/SelectionSet.cpp \
selection/ManipulateMouseTool.cpp \
selection/SelectionMouseTools.cpp \
@@ -195,12 +200,15 @@ darkradiant_SOURCES = main.cpp \
selection/RotateManipulator.cpp \
selection/Manipulatables.cpp \
selection/ScaleManipulator.cpp \
+ selection/group/SelectionGroupManager.cpp \
+ selection/group/SelectionGroupInfoFileModule.cpp \
selection/TranslateManipulator.cpp \
selection/Intersection.cpp \
settings/GameFileLoader.cpp \
settings/Game.cpp \
settings/GameManager.cpp \
settings/PreferenceSystem.cpp \
+ settings/PreferencePage.cpp \
settings/Win32Registry.cpp \
patch/algorithm/General.cpp \
patch/algorithm/Prefab.cpp \
@@ -208,20 +216,20 @@ darkradiant_SOURCES = main.cpp \
patch/PatchCreators.cpp \
patch/PatchNode.cpp \
patch/PatchModule.cpp \
- patch/PatchBezier.cpp \
patch/PatchRenderables.cpp \
patch/PatchTesselation.cpp \
map/RootNode.cpp \
map/MapPosition.cpp \
map/FindMapElements.cpp \
- map/InfoFile.cpp \
+ map/infofile/InfoFileManager.cpp \
+ map/infofile/InfoFile.cpp \
+ map/infofile/InfoFileExporter.cpp \
map/MapFileManager.cpp \
map/algorithm/ChildPrimitives.cpp \
map/algorithm/Skins.cpp \
map/algorithm/Traverse.cpp \
map/algorithm/MapExporter.cpp \
map/algorithm/MapImporter.cpp \
- map/algorithm/InfoFileExporter.cpp \
map/CounterManager.cpp \
map/RegionManager.cpp \
map/PointFile.cpp \
@@ -232,6 +240,8 @@ darkradiant_SOURCES = main.cpp \
map/StartupMapLoader.cpp \
map/MapResourceManager.cpp \
map/MapFormatManager.cpp \
+ map/AasFileManager.cpp \
+ map/RenderableAasFile.cpp \
clipper/ClipPoint.cpp \
clipper/Clipper.cpp \
log/Console.cpp \
diff --git a/radiant/Makefile.in b/radiant/Makefile.in
index 1dfc880..fd28949 100644
--- a/radiant/Makefile.in
+++ b/radiant/Makefile.in
@@ -198,6 +198,7 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
ui/menu/darkradiant-FiltersMenu.$(OBJEXT) \
ui/prefdialog/darkradiant-PrefPage.$(OBJEXT) \
ui/prefdialog/darkradiant-PrefDialog.$(OBJEXT) \
+ ui/prefdialog/darkradiant-PreferenceItem.$(OBJEXT) \
ui/transform/darkradiant-TransformDialog.$(OBJEXT) \
ui/modelselector/darkradiant-MaterialsList.$(OBJEXT) \
ui/modelselector/darkradiant-ModelSelector.$(OBJEXT) \
@@ -224,6 +225,8 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
ui/mousetool/darkradiant-ToolMappingDialog.$(OBJEXT) \
ui/animationpreview/darkradiant-AnimationPreview.$(OBJEXT) \
ui/animationpreview/darkradiant-MD5AnimationViewer.$(OBJEXT) \
+ ui/aas/darkradiant-AasControl.$(OBJEXT) \
+ ui/aas/darkradiant-AasControlDialog.$(OBJEXT) \
xyview/tools/darkradiant-BrushCreatorTool.$(OBJEXT) \
xyview/tools/darkradiant-ClipperTool.$(OBJEXT) \
xyview/darkradiant-XYWnd.$(OBJEXT) \
@@ -236,6 +239,7 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
textool/item/darkradiant-PatchItem.$(OBJEXT) \
textool/item/darkradiant-PatchVertexItem.$(OBJEXT) \
textool/darkradiant-TexTool.$(OBJEXT) \
+ layers/darkradiant-LayerInfoFileModule.$(OBJEXT) \
layers/darkradiant-LayerCommandTarget.$(OBJEXT) \
layers/darkradiant-LayerSystem.$(OBJEXT) \
modulesystem/darkradiant-DynamicLibrary.$(OBJEXT) \
@@ -250,6 +254,7 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
selection/shaderclipboard/darkradiant-ClosestTexturableFinder.$(OBJEXT) \
selection/selectionset/darkradiant-SelectionSetManager.$(OBJEXT) \
selection/selectionset/darkradiant-SelectionSetToolmenu.$(OBJEXT) \
+ selection/selectionset/darkradiant-SelectionSetInfoFileModule.$(OBJEXT) \
selection/selectionset/darkradiant-SelectionSet.$(OBJEXT) \
selection/darkradiant-ManipulateMouseTool.$(OBJEXT) \
selection/darkradiant-SelectionMouseTools.$(OBJEXT) \
@@ -273,12 +278,15 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
selection/darkradiant-RotateManipulator.$(OBJEXT) \
selection/darkradiant-Manipulatables.$(OBJEXT) \
selection/darkradiant-ScaleManipulator.$(OBJEXT) \
+ selection/group/darkradiant-SelectionGroupManager.$(OBJEXT) \
+ selection/group/darkradiant-SelectionGroupInfoFileModule.$(OBJEXT) \
selection/darkradiant-TranslateManipulator.$(OBJEXT) \
selection/darkradiant-Intersection.$(OBJEXT) \
settings/darkradiant-GameFileLoader.$(OBJEXT) \
settings/darkradiant-Game.$(OBJEXT) \
settings/darkradiant-GameManager.$(OBJEXT) \
settings/darkradiant-PreferenceSystem.$(OBJEXT) \
+ settings/darkradiant-PreferencePage.$(OBJEXT) \
settings/darkradiant-Win32Registry.$(OBJEXT) \
patch/algorithm/darkradiant-General.$(OBJEXT) \
patch/algorithm/darkradiant-Prefab.$(OBJEXT) \
@@ -286,20 +294,20 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
patch/darkradiant-PatchCreators.$(OBJEXT) \
patch/darkradiant-PatchNode.$(OBJEXT) \
patch/darkradiant-PatchModule.$(OBJEXT) \
- patch/darkradiant-PatchBezier.$(OBJEXT) \
patch/darkradiant-PatchRenderables.$(OBJEXT) \
patch/darkradiant-PatchTesselation.$(OBJEXT) \
map/darkradiant-RootNode.$(OBJEXT) \
map/darkradiant-MapPosition.$(OBJEXT) \
map/darkradiant-FindMapElements.$(OBJEXT) \
- map/darkradiant-InfoFile.$(OBJEXT) \
+ map/infofile/darkradiant-InfoFileManager.$(OBJEXT) \
+ map/infofile/darkradiant-InfoFile.$(OBJEXT) \
+ map/infofile/darkradiant-InfoFileExporter.$(OBJEXT) \
map/darkradiant-MapFileManager.$(OBJEXT) \
map/algorithm/darkradiant-ChildPrimitives.$(OBJEXT) \
map/algorithm/darkradiant-Skins.$(OBJEXT) \
map/algorithm/darkradiant-Traverse.$(OBJEXT) \
map/algorithm/darkradiant-MapExporter.$(OBJEXT) \
map/algorithm/darkradiant-MapImporter.$(OBJEXT) \
- map/algorithm/darkradiant-InfoFileExporter.$(OBJEXT) \
map/darkradiant-CounterManager.$(OBJEXT) \
map/darkradiant-RegionManager.$(OBJEXT) \
map/darkradiant-PointFile.$(OBJEXT) \
@@ -310,6 +318,8 @@ am_darkradiant_OBJECTS = darkradiant-main.$(OBJEXT) \
map/darkradiant-StartupMapLoader.$(OBJEXT) \
map/darkradiant-MapResourceManager.$(OBJEXT) \
map/darkradiant-MapFormatManager.$(OBJEXT) \
+ map/darkradiant-AasFileManager.$(OBJEXT) \
+ map/darkradiant-RenderableAasFile.$(OBJEXT) \
clipper/darkradiant-ClipPoint.$(OBJEXT) \
clipper/darkradiant-Clipper.$(OBJEXT) \
log/darkradiant-Console.$(OBJEXT) \
@@ -928,6 +938,7 @@ darkradiant_SOURCES = main.cpp \
ui/menu/FiltersMenu.cpp \
ui/prefdialog/PrefPage.cpp \
ui/prefdialog/PrefDialog.cpp \
+ ui/prefdialog/PreferenceItem.cpp \
ui/transform/TransformDialog.cpp \
ui/modelselector/MaterialsList.cpp \
ui/modelselector/ModelSelector.cpp \
@@ -954,6 +965,8 @@ darkradiant_SOURCES = main.cpp \
ui/mousetool/ToolMappingDialog.cpp \
ui/animationpreview/AnimationPreview.cpp \
ui/animationpreview/MD5AnimationViewer.cpp \
+ ui/aas/AasControl.cpp \
+ ui/aas/AasControlDialog.cpp \
xyview/tools/BrushCreatorTool.cpp \
xyview/tools/ClipperTool.cpp \
xyview/XYWnd.cpp \
@@ -966,6 +979,7 @@ darkradiant_SOURCES = main.cpp \
textool/item/PatchItem.cpp \
textool/item/PatchVertexItem.cpp \
textool/TexTool.cpp \
+ layers/LayerInfoFileModule.cpp \
layers/LayerCommandTarget.cpp \
layers/LayerSystem.cpp \
modulesystem/DynamicLibrary.cpp \
@@ -980,6 +994,7 @@ darkradiant_SOURCES = main.cpp \
selection/shaderclipboard/ClosestTexturableFinder.cpp \
selection/selectionset/SelectionSetManager.cpp \
selection/selectionset/SelectionSetToolmenu.cpp \
+ selection/selectionset/SelectionSetInfoFileModule.cpp \
selection/selectionset/SelectionSet.cpp \
selection/ManipulateMouseTool.cpp \
selection/SelectionMouseTools.cpp \
@@ -1003,12 +1018,15 @@ darkradiant_SOURCES = main.cpp \
selection/RotateManipulator.cpp \
selection/Manipulatables.cpp \
selection/ScaleManipulator.cpp \
+ selection/group/SelectionGroupManager.cpp \
+ selection/group/SelectionGroupInfoFileModule.cpp \
selection/TranslateManipulator.cpp \
selection/Intersection.cpp \
settings/GameFileLoader.cpp \
settings/Game.cpp \
settings/GameManager.cpp \
settings/PreferenceSystem.cpp \
+ settings/PreferencePage.cpp \
settings/Win32Registry.cpp \
patch/algorithm/General.cpp \
patch/algorithm/Prefab.cpp \
@@ -1016,20 +1034,20 @@ darkradiant_SOURCES = main.cpp \
patch/PatchCreators.cpp \
patch/PatchNode.cpp \
patch/PatchModule.cpp \
- patch/PatchBezier.cpp \
patch/PatchRenderables.cpp \
patch/PatchTesselation.cpp \
map/RootNode.cpp \
map/MapPosition.cpp \
map/FindMapElements.cpp \
- map/InfoFile.cpp \
+ map/infofile/InfoFileManager.cpp \
+ map/infofile/InfoFile.cpp \
+ map/infofile/InfoFileExporter.cpp \
map/MapFileManager.cpp \
map/algorithm/ChildPrimitives.cpp \
map/algorithm/Skins.cpp \
map/algorithm/Traverse.cpp \
map/algorithm/MapExporter.cpp \
map/algorithm/MapImporter.cpp \
- map/algorithm/InfoFileExporter.cpp \
map/CounterManager.cpp \
map/RegionManager.cpp \
map/PointFile.cpp \
@@ -1040,6 +1058,8 @@ darkradiant_SOURCES = main.cpp \
map/StartupMapLoader.cpp \
map/MapResourceManager.cpp \
map/MapFormatManager.cpp \
+ map/AasFileManager.cpp \
+ map/RenderableAasFile.cpp \
clipper/ClipPoint.cpp \
clipper/Clipper.cpp \
log/Console.cpp \
@@ -1540,6 +1560,9 @@ ui/prefdialog/darkradiant-PrefPage.$(OBJEXT): \
ui/prefdialog/darkradiant-PrefDialog.$(OBJEXT): \
ui/prefdialog/$(am__dirstamp) \
ui/prefdialog/$(DEPDIR)/$(am__dirstamp)
+ui/prefdialog/darkradiant-PreferenceItem.$(OBJEXT): \
+ ui/prefdialog/$(am__dirstamp) \
+ ui/prefdialog/$(DEPDIR)/$(am__dirstamp)
ui/transform/$(am__dirstamp):
@$(MKDIR_P) ui/transform
@: > ui/transform/$(am__dirstamp)
@@ -1673,6 +1696,16 @@ ui/animationpreview/darkradiant-AnimationPreview.$(OBJEXT): \
ui/animationpreview/darkradiant-MD5AnimationViewer.$(OBJEXT): \
ui/animationpreview/$(am__dirstamp) \
ui/animationpreview/$(DEPDIR)/$(am__dirstamp)
+ui/aas/$(am__dirstamp):
+ @$(MKDIR_P) ui/aas
+ @: > ui/aas/$(am__dirstamp)
+ui/aas/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) ui/aas/$(DEPDIR)
+ @: > ui/aas/$(DEPDIR)/$(am__dirstamp)
+ui/aas/darkradiant-AasControl.$(OBJEXT): ui/aas/$(am__dirstamp) \
+ ui/aas/$(DEPDIR)/$(am__dirstamp)
+ui/aas/darkradiant-AasControlDialog.$(OBJEXT): ui/aas/$(am__dirstamp) \
+ ui/aas/$(DEPDIR)/$(am__dirstamp)
xyview/tools/$(am__dirstamp):
@$(MKDIR_P) xyview/tools
@: > xyview/tools/$(am__dirstamp)
@@ -1734,6 +1767,8 @@ layers/$(am__dirstamp):
layers/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) layers/$(DEPDIR)
@: > layers/$(DEPDIR)/$(am__dirstamp)
+layers/darkradiant-LayerInfoFileModule.$(OBJEXT): \
+ layers/$(am__dirstamp) layers/$(DEPDIR)/$(am__dirstamp)
layers/darkradiant-LayerCommandTarget.$(OBJEXT): \
layers/$(am__dirstamp) layers/$(DEPDIR)/$(am__dirstamp)
layers/darkradiant-LayerSystem.$(OBJEXT): layers/$(am__dirstamp) \
@@ -1803,6 +1838,9 @@ selection/selectionset/darkradiant-SelectionSetManager.$(OBJEXT): \
selection/selectionset/darkradiant-SelectionSetToolmenu.$(OBJEXT): \
selection/selectionset/$(am__dirstamp) \
selection/selectionset/$(DEPDIR)/$(am__dirstamp)
+selection/selectionset/darkradiant-SelectionSetInfoFileModule.$(OBJEXT): \
+ selection/selectionset/$(am__dirstamp) \
+ selection/selectionset/$(DEPDIR)/$(am__dirstamp)
selection/selectionset/darkradiant-SelectionSet.$(OBJEXT): \
selection/selectionset/$(am__dirstamp) \
selection/selectionset/$(DEPDIR)/$(am__dirstamp)
@@ -1866,6 +1904,18 @@ selection/darkradiant-Manipulatables.$(OBJEXT): \
selection/$(am__dirstamp) selection/$(DEPDIR)/$(am__dirstamp)
selection/darkradiant-ScaleManipulator.$(OBJEXT): \
selection/$(am__dirstamp) selection/$(DEPDIR)/$(am__dirstamp)
+selection/group/$(am__dirstamp):
+ @$(MKDIR_P) selection/group
+ @: > selection/group/$(am__dirstamp)
+selection/group/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) selection/group/$(DEPDIR)
+ @: > selection/group/$(DEPDIR)/$(am__dirstamp)
+selection/group/darkradiant-SelectionGroupManager.$(OBJEXT): \
+ selection/group/$(am__dirstamp) \
+ selection/group/$(DEPDIR)/$(am__dirstamp)
+selection/group/darkradiant-SelectionGroupInfoFileModule.$(OBJEXT): \
+ selection/group/$(am__dirstamp) \
+ selection/group/$(DEPDIR)/$(am__dirstamp)
selection/darkradiant-TranslateManipulator.$(OBJEXT): \
selection/$(am__dirstamp) selection/$(DEPDIR)/$(am__dirstamp)
selection/darkradiant-Intersection.$(OBJEXT): \
@@ -1884,6 +1934,8 @@ settings/darkradiant-GameManager.$(OBJEXT): settings/$(am__dirstamp) \
settings/$(DEPDIR)/$(am__dirstamp)
settings/darkradiant-PreferenceSystem.$(OBJEXT): \
settings/$(am__dirstamp) settings/$(DEPDIR)/$(am__dirstamp)
+settings/darkradiant-PreferencePage.$(OBJEXT): \
+ settings/$(am__dirstamp) settings/$(DEPDIR)/$(am__dirstamp)
settings/darkradiant-Win32Registry.$(OBJEXT): \
settings/$(am__dirstamp) settings/$(DEPDIR)/$(am__dirstamp)
patch/algorithm/$(am__dirstamp):
@@ -1912,8 +1964,6 @@ patch/darkradiant-PatchNode.$(OBJEXT): patch/$(am__dirstamp) \
patch/$(DEPDIR)/$(am__dirstamp)
patch/darkradiant-PatchModule.$(OBJEXT): patch/$(am__dirstamp) \
patch/$(DEPDIR)/$(am__dirstamp)
-patch/darkradiant-PatchBezier.$(OBJEXT): patch/$(am__dirstamp) \
- patch/$(DEPDIR)/$(am__dirstamp)
patch/darkradiant-PatchRenderables.$(OBJEXT): patch/$(am__dirstamp) \
patch/$(DEPDIR)/$(am__dirstamp)
patch/darkradiant-PatchTesselation.$(OBJEXT): patch/$(am__dirstamp) \
@@ -1930,8 +1980,21 @@ map/darkradiant-MapPosition.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/darkradiant-FindMapElements.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
-map/darkradiant-InfoFile.$(OBJEXT): map/$(am__dirstamp) \
- map/$(DEPDIR)/$(am__dirstamp)
+map/infofile/$(am__dirstamp):
+ @$(MKDIR_P) map/infofile
+ @: > map/infofile/$(am__dirstamp)
+map/infofile/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) map/infofile/$(DEPDIR)
+ @: > map/infofile/$(DEPDIR)/$(am__dirstamp)
+map/infofile/darkradiant-InfoFileManager.$(OBJEXT): \
+ map/infofile/$(am__dirstamp) \
+ map/infofile/$(DEPDIR)/$(am__dirstamp)
+map/infofile/darkradiant-InfoFile.$(OBJEXT): \
+ map/infofile/$(am__dirstamp) \
+ map/infofile/$(DEPDIR)/$(am__dirstamp)
+map/infofile/darkradiant-InfoFileExporter.$(OBJEXT): \
+ map/infofile/$(am__dirstamp) \
+ map/infofile/$(DEPDIR)/$(am__dirstamp)
map/darkradiant-MapFileManager.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/algorithm/$(am__dirstamp):
@@ -1955,9 +2018,6 @@ map/algorithm/darkradiant-MapExporter.$(OBJEXT): \
map/algorithm/darkradiant-MapImporter.$(OBJEXT): \
map/algorithm/$(am__dirstamp) \
map/algorithm/$(DEPDIR)/$(am__dirstamp)
-map/algorithm/darkradiant-InfoFileExporter.$(OBJEXT): \
- map/algorithm/$(am__dirstamp) \
- map/algorithm/$(DEPDIR)/$(am__dirstamp)
map/darkradiant-CounterManager.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/darkradiant-RegionManager.$(OBJEXT): map/$(am__dirstamp) \
@@ -1978,6 +2038,10 @@ map/darkradiant-MapResourceManager.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
map/darkradiant-MapFormatManager.$(OBJEXT): map/$(am__dirstamp) \
map/$(DEPDIR)/$(am__dirstamp)
+map/darkradiant-AasFileManager.$(OBJEXT): map/$(am__dirstamp) \
+ map/$(DEPDIR)/$(am__dirstamp)
+map/darkradiant-RenderableAasFile.$(OBJEXT): map/$(am__dirstamp) \
+ map/$(DEPDIR)/$(am__dirstamp)
clipper/$(am__dirstamp):
@$(MKDIR_P) clipper
@: > clipper/$(am__dirstamp)
@@ -2053,6 +2117,7 @@ mostlyclean-compile:
-rm -f log/*.$(OBJEXT)
-rm -f map/*.$(OBJEXT)
-rm -f map/algorithm/*.$(OBJEXT)
+ -rm -f map/infofile/*.$(OBJEXT)
-rm -f modulesystem/*.$(OBJEXT)
-rm -f namespace/*.$(OBJEXT)
-rm -f patch/*.$(OBJEXT)
@@ -2065,12 +2130,14 @@ mostlyclean-compile:
-rm -f selection/*.$(OBJEXT)
-rm -f selection/algorithm/*.$(OBJEXT)
-rm -f selection/clipboard/*.$(OBJEXT)
+ -rm -f selection/group/*.$(OBJEXT)
-rm -f selection/selectionset/*.$(OBJEXT)
-rm -f selection/shaderclipboard/*.$(OBJEXT)
-rm -f settings/*.$(OBJEXT)
-rm -f test/*.$(OBJEXT)
-rm -f textool/*.$(OBJEXT)
-rm -f textool/item/*.$(OBJEXT)
+ -rm -f ui/aas/*.$(OBJEXT)
-rm -f ui/about/*.$(OBJEXT)
-rm -f ui/animationpreview/*.$(OBJEXT)
-rm -f ui/brush/*.$(OBJEXT)
@@ -2132,6 +2199,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at clipper/$(DEPDIR)/darkradiant-ClipPoint.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at clipper/$(DEPDIR)/darkradiant-Clipper.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at layers/$(DEPDIR)/darkradiant-LayerCommandTarget.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at layers/$(DEPDIR)/darkradiant-LayerSystem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at log/$(DEPDIR)/darkradiant-COutRedirector.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at log/$(DEPDIR)/darkradiant-Console.Po at am__quote@
@@ -2140,10 +2208,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at log/$(DEPDIR)/darkradiant-LogStreamBuf.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at log/$(DEPDIR)/darkradiant-LogWriter.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at log/$(DEPDIR)/darkradiant-StringLogDevice.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-AasFileManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-AutoSaver.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-CounterManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-FindMapElements.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-InfoFile.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-Map.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-MapFileManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-MapFormatManager.Po at am__quote@
@@ -2153,14 +2221,17 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-MapResourceManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-PointFile.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-RegionManager.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-RenderableAasFile.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-RootNode.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/$(DEPDIR)/darkradiant-StartupMapLoader.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-ChildPrimitives.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-MapExporter.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-MapImporter.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-Skins.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at map/algorithm/$(DEPDIR)/darkradiant-Traverse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at map/infofile/$(DEPDIR)/darkradiant-InfoFile.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at modulesystem/$(DEPDIR)/darkradiant-ApplicationContextImpl.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at modulesystem/$(DEPDIR)/darkradiant-DynamicLibrary.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at modulesystem/$(DEPDIR)/darkradiant-DynamicLibraryLoader.Po at am__quote@
@@ -2170,7 +2241,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at namespace/$(DEPDIR)/darkradiant-Namespace.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at namespace/$(DEPDIR)/darkradiant-NamespaceFactory.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at patch/$(DEPDIR)/darkradiant-Patch.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at patch/$(DEPDIR)/darkradiant-PatchBezier.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at patch/$(DEPDIR)/darkradiant-PatchCreators.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at patch/$(DEPDIR)/darkradiant-PatchModule.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at patch/$(DEPDIR)/darkradiant-PatchNode.Po at am__quote@
@@ -2221,7 +2291,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at selection/algorithm/$(DEPDIR)/darkradiant-Shader.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/algorithm/$(DEPDIR)/darkradiant-Transformation.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/clipboard/$(DEPDIR)/darkradiant-Clipboard.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/selectionset/$(DEPDIR)/darkradiant-SelectionSet.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetManager.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetToolmenu.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at selection/shaderclipboard/$(DEPDIR)/darkradiant-ClosestTexturableFinder.Po at am__quote@
@@ -2230,6 +2303,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-Game.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-GameFileLoader.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-GameManager.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-PreferencePage.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-PreferenceSystem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at settings/$(DEPDIR)/darkradiant-Win32Registry.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at test/$(DEPDIR)/facePlaneTest.Po at am__quote@
@@ -2240,6 +2314,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at textool/item/$(DEPDIR)/darkradiant-FaceVertexItem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at textool/item/$(DEPDIR)/darkradiant-PatchItem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at textool/item/$(DEPDIR)/darkradiant-PatchVertexItem.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ui/aas/$(DEPDIR)/darkradiant-AasControl.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/about/$(DEPDIR)/darkradiant-AboutDialog.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/animationpreview/$(DEPDIR)/darkradiant-AnimationPreview.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/animationpreview/$(DEPDIR)/darkradiant-MD5AnimationViewer.Po at am__quote@
@@ -2316,6 +2392,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote at ui/prefabselector/$(DEPDIR)/darkradiant-PrefabSelector.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/prefdialog/$(DEPDIR)/darkradiant-PrefDialog.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/prefdialog/$(DEPDIR)/darkradiant-PrefPage.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/splash/$(DEPDIR)/darkradiant-Splash.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/surfaceinspector/$(DEPDIR)/darkradiant-SurfaceInspector.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ui/texturebrowser/$(DEPDIR)/darkradiant-TextureBrowser.Po at am__quote@
@@ -3681,6 +3758,20 @@ ui/prefdialog/darkradiant-PrefDialog.obj: ui/prefdialog/PrefDialog.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/prefdialog/darkradiant-PrefDialog.obj `if test -f 'ui/prefdialog/PrefDialog.cpp'; then $(CYGPATH_W) 'ui/prefdialog/PrefDialog.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/prefdialog/PrefDialog.cpp'; fi`
+ui/prefdialog/darkradiant-PreferenceItem.o: ui/prefdialog/PreferenceItem.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/prefdialog/darkradiant-PreferenceItem.o -MD -MP -MF ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Tpo -c -o ui/prefdialog/darkradiant-PreferenceItem.o `test -f 'ui/prefdialog/PreferenceItem.cpp' || echo '$(srcdir)/'`ui/prefdialog/PreferenceItem.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Tpo ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/prefdialog/PreferenceItem.cpp' object='ui/prefdialog/darkradiant-PreferenceItem.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/prefdialog/darkradiant-PreferenceItem.o `test -f 'ui/prefdialog/PreferenceItem.cpp' || echo '$(srcdir)/'`ui/prefdialog/PreferenceItem.cpp
+
+ui/prefdialog/darkradiant-PreferenceItem.obj: ui/prefdialog/PreferenceItem.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/prefdialog/darkradiant-PreferenceItem.obj -MD -MP -MF ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Tpo -c -o ui/prefdialog/darkradiant-PreferenceItem.obj `if test -f 'ui/prefdialog/PreferenceItem.cpp'; then $(CYGPATH_W) 'ui/prefdialog/PreferenceItem.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/prefdialog/PreferenceItem.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Tpo ui/prefdialog/$(DEPDIR)/darkradiant-PreferenceItem.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/prefdialog/PreferenceItem.cpp' object='ui/prefdialog/darkradiant-PreferenceItem.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/prefdialog/darkradiant-PreferenceItem.obj `if test -f 'ui/prefdialog/PreferenceItem.cpp'; then $(CYGPATH_W) 'ui/prefdialog/PreferenceItem.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/prefdialog/PreferenceItem.cpp'; fi`
+
ui/transform/darkradiant-TransformDialog.o: ui/transform/TransformDialog.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/transform/darkradiant-TransformDialog.o -MD -MP -MF ui/transform/$(DEPDIR)/darkradiant-TransformDialog.Tpo -c -o ui/transform/darkradiant-TransformDialog.o `test -f 'ui/transform/TransformDialog.cpp' || echo '$(srcdir)/'`ui/transform/TransformDialog.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/transform/$(DEPDIR)/darkradiant-TransformDialog.Tpo ui/transform/$(DEPDIR)/darkradiant-TransformDialog.Po
@@ -4045,6 +4136,34 @@ ui/animationpreview/darkradiant-MD5AnimationViewer.obj: ui/animationpreview/MD5A
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/animationpreview/darkradiant-MD5AnimationViewer.obj `if test -f 'ui/animationpreview/MD5AnimationViewer.cpp'; then $(CYGPATH_W) 'ui/animationpreview/MD5AnimationViewer.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/animationpreview/MD5AnimationViewer.cpp'; fi`
+ui/aas/darkradiant-AasControl.o: ui/aas/AasControl.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/aas/darkradiant-AasControl.o -MD -MP -MF ui/aas/$(DEPDIR)/darkradiant-AasControl.Tpo -c -o ui/aas/darkradiant-AasControl.o `test -f 'ui/aas/AasControl.cpp' || echo '$(srcdir)/'`ui/aas/AasControl.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/aas/$(DEPDIR)/darkradiant-AasControl.Tpo ui/aas/$(DEPDIR)/darkradiant-AasControl.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/aas/AasControl.cpp' object='ui/aas/darkradiant-AasControl.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/aas/darkradiant-AasControl.o `test -f 'ui/aas/AasControl.cpp' || echo '$(srcdir)/'`ui/aas/AasControl.cpp
+
+ui/aas/darkradiant-AasControl.obj: ui/aas/AasControl.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/aas/darkradiant-AasControl.obj -MD -MP -MF ui/aas/$(DEPDIR)/darkradiant-AasControl.Tpo -c -o ui/aas/darkradiant-AasControl.obj `if test -f 'ui/aas/AasControl.cpp'; then $(CYGPATH_W) 'ui/aas/AasControl.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/aas/AasControl.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/aas/$(DEPDIR)/darkradiant-AasControl.Tpo ui/aas/$(DEPDIR)/darkradiant-AasControl.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/aas/AasControl.cpp' object='ui/aas/darkradiant-AasControl.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/aas/darkradiant-AasControl.obj `if test -f 'ui/aas/AasControl.cpp'; then $(CYGPATH_W) 'ui/aas/AasControl.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/aas/AasControl.cpp'; fi`
+
+ui/aas/darkradiant-AasControlDialog.o: ui/aas/AasControlDialog.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/aas/darkradiant-AasControlDialog.o -MD -MP -MF ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Tpo -c -o ui/aas/darkradiant-AasControlDialog.o `test -f 'ui/aas/AasControlDialog.cpp' || echo '$(srcdir)/'`ui/aas/AasControlDialog.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Tpo ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/aas/AasControlDialog.cpp' object='ui/aas/darkradiant-AasControlDialog.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/aas/darkradiant-AasControlDialog.o `test -f 'ui/aas/AasControlDialog.cpp' || echo '$(srcdir)/'`ui/aas/AasControlDialog.cpp
+
+ui/aas/darkradiant-AasControlDialog.obj: ui/aas/AasControlDialog.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ui/aas/darkradiant-AasControlDialog.obj -MD -MP -MF ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Tpo -c -o ui/aas/darkradiant-AasControlDialog.obj `if test -f 'ui/aas/AasControlDialog.cpp'; then $(CYGPATH_W) 'ui/aas/AasControlDialog.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/aas/AasControlDialog.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Tpo ui/aas/$(DEPDIR)/darkradiant-AasControlDialog.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ui/aas/AasControlDialog.cpp' object='ui/aas/darkradiant-AasControlDialog.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ui/aas/darkradiant-AasControlDialog.obj `if test -f 'ui/aas/AasControlDialog.cpp'; then $(CYGPATH_W) 'ui/aas/AasControlDialog.cpp'; else $(CYGPATH_W) '$(srcdir)/ui/aas/AasControlDialog.cpp'; fi`
+
xyview/tools/darkradiant-BrushCreatorTool.o: xyview/tools/BrushCreatorTool.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT xyview/tools/darkradiant-BrushCreatorTool.o -MD -MP -MF xyview/tools/$(DEPDIR)/darkradiant-BrushCreatorTool.Tpo -c -o xyview/tools/darkradiant-BrushCreatorTool.o `test -f 'xyview/tools/BrushCreatorTool.cpp' || echo '$(srcdir)/'`xyview/tools/BrushCreatorTool.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) xyview/tools/$(DEPDIR)/darkradiant-BrushCreatorTool.Tpo xyview/tools/$(DEPDIR)/darkradiant-BrushCreatorTool.Po
@@ -4213,6 +4332,20 @@ textool/darkradiant-TexTool.obj: textool/TexTool.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o textool/darkradiant-TexTool.obj `if test -f 'textool/TexTool.cpp'; then $(CYGPATH_W) 'textool/TexTool.cpp'; else $(CYGPATH_W) '$(srcdir)/textool/TexTool.cpp'; fi`
+layers/darkradiant-LayerInfoFileModule.o: layers/LayerInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT layers/darkradiant-LayerInfoFileModule.o -MD -MP -MF layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Tpo -c -o layers/darkradiant-LayerInfoFileModule.o `test -f 'layers/LayerInfoFileModule.cpp' || echo '$(srcdir)/'`layers/LayerInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Tpo layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='layers/LayerInfoFileModule.cpp' object='layers/darkradiant-LayerInfoFileModule.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o layers/darkradiant-LayerInfoFileModule.o `test -f 'layers/LayerInfoFileModule.cpp' || echo '$(srcdir)/'`layers/LayerInfoFileModule.cpp
+
+layers/darkradiant-LayerInfoFileModule.obj: layers/LayerInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT layers/darkradiant-LayerInfoFileModule.obj -MD -MP -MF layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Tpo -c -o layers/darkradiant-LayerInfoFileModule.obj `if test -f 'layers/LayerInfoFileModule.cpp'; then $(CYGPATH_W) 'layers/LayerInfoFileModule.cpp'; else $(CYGPATH_W) '$(srcdir)/layers/LayerInfoFileModule.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Tpo layers/$(DEPDIR)/darkradiant-LayerInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='layers/LayerInfoFileModule.cpp' object='layers/darkradiant-LayerInfoFileModule.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o layers/darkradiant-LayerInfoFileModule.obj `if test -f 'layers/LayerInfoFileModule.cpp'; then $(CYGPATH_W) 'layers/LayerInfoFileModule.cpp'; else $(CYGPATH_W) '$(srcdir)/layers/LayerInfoFileModule.cpp'; fi`
+
layers/darkradiant-LayerCommandTarget.o: layers/LayerCommandTarget.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT layers/darkradiant-LayerCommandTarget.o -MD -MP -MF layers/$(DEPDIR)/darkradiant-LayerCommandTarget.Tpo -c -o layers/darkradiant-LayerCommandTarget.o `test -f 'layers/LayerCommandTarget.cpp' || echo '$(srcdir)/'`layers/LayerCommandTarget.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) layers/$(DEPDIR)/darkradiant-LayerCommandTarget.Tpo layers/$(DEPDIR)/darkradiant-LayerCommandTarget.Po
@@ -4409,6 +4542,20 @@ selection/selectionset/darkradiant-SelectionSetToolmenu.obj: selection/selection
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/selectionset/darkradiant-SelectionSetToolmenu.obj `if test -f 'selection/selectionset/SelectionSetToolmenu.cpp'; then $(CYGPATH_W) 'selection/selectionset/SelectionSetToolmenu.cpp'; else $(CYGPATH_W) '$(srcdir)/selection/selectionset/SelectionSetToolmenu.cpp'; fi`
+selection/selectionset/darkradiant-SelectionSetInfoFileModule.o: selection/selectionset/SelectionSetInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/selectionset/darkradiant-SelectionSetInfoFileModule.o -MD -MP -MF selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Tpo -c -o selection/selectionset/darkradiant-SelectionSetInfoFileModule.o `test -f 'selection/selectionset/SelectionSetInfoFileModule.cpp' || echo '$(srcdir)/'`selection/selectionset/SelectionSetIn [...]
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Tpo selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/selectionset/SelectionSetInfoFileModule.cpp' object='selection/selectionset/darkradiant-SelectionSetInfoFileModule.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/selectionset/darkradiant-SelectionSetInfoFileModule.o `test -f 'selection/selectionset/SelectionSetInfoFileModule.cpp' || echo '$(srcdir)/'`selection/selectionset/SelectionSetInfoFileModule.cpp
+
+selection/selectionset/darkradiant-SelectionSetInfoFileModule.obj: selection/selectionset/SelectionSetInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/selectionset/darkradiant-SelectionSetInfoFileModule.obj -MD -MP -MF selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Tpo -c -o selection/selectionset/darkradiant-SelectionSetInfoFileModule.obj `if test -f 'selection/selectionset/SelectionSetInfoFileModule.cpp'; then $(CYGPATH_W) 'selection/selectionset/Selectio [...]
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Tpo selection/selectionset/$(DEPDIR)/darkradiant-SelectionSetInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/selectionset/SelectionSetInfoFileModule.cpp' object='selection/selectionset/darkradiant-SelectionSetInfoFileModule.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/selectionset/darkradiant-SelectionSetInfoFileModule.obj `if test -f 'selection/selectionset/SelectionSetInfoFileModule.cpp'; then $(CYGPATH_W) 'selection/selectionset/SelectionSetInfoFileModule.cpp'; else $(CYGPATH_W) '$(srcdir)/selection/selectionset/SelectionSetInfoFileModule.cpp'; fi`
+
selection/selectionset/darkradiant-SelectionSet.o: selection/selectionset/SelectionSet.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/selectionset/darkradiant-SelectionSet.o -MD -MP -MF selection/selectionset/$(DEPDIR)/darkradiant-SelectionSet.Tpo -c -o selection/selectionset/darkradiant-SelectionSet.o `test -f 'selection/selectionset/SelectionSet.cpp' || echo '$(srcdir)/'`selection/selectionset/SelectionSet.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/selectionset/$(DEPDIR)/darkradiant-SelectionSet.Tpo selection/selectionset/$(DEPDIR)/darkradiant-SelectionSet.Po
@@ -4731,6 +4878,34 @@ selection/darkradiant-ScaleManipulator.obj: selection/ScaleManipulator.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/darkradiant-ScaleManipulator.obj `if test -f 'selection/ScaleManipulator.cpp'; then $(CYGPATH_W) 'selection/ScaleManipulator.cpp'; else $(CYGPATH_W) '$(srcdir)/selection/ScaleManipulator.cpp'; fi`
+selection/group/darkradiant-SelectionGroupManager.o: selection/group/SelectionGroupManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/group/darkradiant-SelectionGroupManager.o -MD -MP -MF selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Tpo -c -o selection/group/darkradiant-SelectionGroupManager.o `test -f 'selection/group/SelectionGroupManager.cpp' || echo '$(srcdir)/'`selection/group/SelectionGroupManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Tpo selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/group/SelectionGroupManager.cpp' object='selection/group/darkradiant-SelectionGroupManager.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/group/darkradiant-SelectionGroupManager.o `test -f 'selection/group/SelectionGroupManager.cpp' || echo '$(srcdir)/'`selection/group/SelectionGroupManager.cpp
+
+selection/group/darkradiant-SelectionGroupManager.obj: selection/group/SelectionGroupManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/group/darkradiant-SelectionGroupManager.obj -MD -MP -MF selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Tpo -c -o selection/group/darkradiant-SelectionGroupManager.obj `if test -f 'selection/group/SelectionGroupManager.cpp'; then $(CYGPATH_W) 'selection/group/SelectionGroupManager.cpp'; else $(CYGPATH_W) '$(srcdir)/select [...]
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Tpo selection/group/$(DEPDIR)/darkradiant-SelectionGroupManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/group/SelectionGroupManager.cpp' object='selection/group/darkradiant-SelectionGroupManager.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/group/darkradiant-SelectionGroupManager.obj `if test -f 'selection/group/SelectionGroupManager.cpp'; then $(CYGPATH_W) 'selection/group/SelectionGroupManager.cpp'; else $(CYGPATH_W) '$(srcdir)/selection/group/SelectionGroupManager.cpp'; fi`
+
+selection/group/darkradiant-SelectionGroupInfoFileModule.o: selection/group/SelectionGroupInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/group/darkradiant-SelectionGroupInfoFileModule.o -MD -MP -MF selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Tpo -c -o selection/group/darkradiant-SelectionGroupInfoFileModule.o `test -f 'selection/group/SelectionGroupInfoFileModule.cpp' || echo '$(srcdir)/'`selection/group/SelectionGroupInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Tpo selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/group/SelectionGroupInfoFileModule.cpp' object='selection/group/darkradiant-SelectionGroupInfoFileModule.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/group/darkradiant-SelectionGroupInfoFileModule.o `test -f 'selection/group/SelectionGroupInfoFileModule.cpp' || echo '$(srcdir)/'`selection/group/SelectionGroupInfoFileModule.cpp
+
+selection/group/darkradiant-SelectionGroupInfoFileModule.obj: selection/group/SelectionGroupInfoFileModule.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/group/darkradiant-SelectionGroupInfoFileModule.obj -MD -MP -MF selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Tpo -c -o selection/group/darkradiant-SelectionGroupInfoFileModule.obj `if test -f 'selection/group/SelectionGroupInfoFileModule.cpp'; then $(CYGPATH_W) 'selection/group/SelectionGroupInfoFileModule.cpp'; [...]
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Tpo selection/group/$(DEPDIR)/darkradiant-SelectionGroupInfoFileModule.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='selection/group/SelectionGroupInfoFileModule.cpp' object='selection/group/darkradiant-SelectionGroupInfoFileModule.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o selection/group/darkradiant-SelectionGroupInfoFileModule.obj `if test -f 'selection/group/SelectionGroupInfoFileModule.cpp'; then $(CYGPATH_W) 'selection/group/SelectionGroupInfoFileModule.cpp'; else $(CYGPATH_W) '$(srcdir)/selection/group/SelectionGroupInfoFileModule.cpp'; fi`
+
selection/darkradiant-TranslateManipulator.o: selection/TranslateManipulator.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT selection/darkradiant-TranslateManipulator.o -MD -MP -MF selection/$(DEPDIR)/darkradiant-TranslateManipulator.Tpo -c -o selection/darkradiant-TranslateManipulator.o `test -f 'selection/TranslateManipulator.cpp' || echo '$(srcdir)/'`selection/TranslateManipulator.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) selection/$(DEPDIR)/darkradiant-TranslateManipulator.Tpo selection/$(DEPDIR)/darkradiant-TranslateManipulator.Po
@@ -4815,6 +4990,20 @@ settings/darkradiant-PreferenceSystem.obj: settings/PreferenceSystem.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o settings/darkradiant-PreferenceSystem.obj `if test -f 'settings/PreferenceSystem.cpp'; then $(CYGPATH_W) 'settings/PreferenceSystem.cpp'; else $(CYGPATH_W) '$(srcdir)/settings/PreferenceSystem.cpp'; fi`
+settings/darkradiant-PreferencePage.o: settings/PreferencePage.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT settings/darkradiant-PreferencePage.o -MD -MP -MF settings/$(DEPDIR)/darkradiant-PreferencePage.Tpo -c -o settings/darkradiant-PreferencePage.o `test -f 'settings/PreferencePage.cpp' || echo '$(srcdir)/'`settings/PreferencePage.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) settings/$(DEPDIR)/darkradiant-PreferencePage.Tpo settings/$(DEPDIR)/darkradiant-PreferencePage.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='settings/PreferencePage.cpp' object='settings/darkradiant-PreferencePage.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o settings/darkradiant-PreferencePage.o `test -f 'settings/PreferencePage.cpp' || echo '$(srcdir)/'`settings/PreferencePage.cpp
+
+settings/darkradiant-PreferencePage.obj: settings/PreferencePage.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT settings/darkradiant-PreferencePage.obj -MD -MP -MF settings/$(DEPDIR)/darkradiant-PreferencePage.Tpo -c -o settings/darkradiant-PreferencePage.obj `if test -f 'settings/PreferencePage.cpp'; then $(CYGPATH_W) 'settings/PreferencePage.cpp'; else $(CYGPATH_W) '$(srcdir)/settings/PreferencePage.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) settings/$(DEPDIR)/darkradiant-PreferencePage.Tpo settings/$(DEPDIR)/darkradiant-PreferencePage.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='settings/PreferencePage.cpp' object='settings/darkradiant-PreferencePage.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o settings/darkradiant-PreferencePage.obj `if test -f 'settings/PreferencePage.cpp'; then $(CYGPATH_W) 'settings/PreferencePage.cpp'; else $(CYGPATH_W) '$(srcdir)/settings/PreferencePage.cpp'; fi`
+
settings/darkradiant-Win32Registry.o: settings/Win32Registry.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT settings/darkradiant-Win32Registry.o -MD -MP -MF settings/$(DEPDIR)/darkradiant-Win32Registry.Tpo -c -o settings/darkradiant-Win32Registry.o `test -f 'settings/Win32Registry.cpp' || echo '$(srcdir)/'`settings/Win32Registry.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) settings/$(DEPDIR)/darkradiant-Win32Registry.Tpo settings/$(DEPDIR)/darkradiant-Win32Registry.Po
@@ -4913,20 +5102,6 @@ patch/darkradiant-PatchModule.obj: patch/PatchModule.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o patch/darkradiant-PatchModule.obj `if test -f 'patch/PatchModule.cpp'; then $(CYGPATH_W) 'patch/PatchModule.cpp'; else $(CYGPATH_W) '$(srcdir)/patch/PatchModule.cpp'; fi`
-patch/darkradiant-PatchBezier.o: patch/PatchBezier.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT patch/darkradiant-PatchBezier.o -MD -MP -MF patch/$(DEPDIR)/darkradiant-PatchBezier.Tpo -c -o patch/darkradiant-PatchBezier.o `test -f 'patch/PatchBezier.cpp' || echo '$(srcdir)/'`patch/PatchBezier.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) patch/$(DEPDIR)/darkradiant-PatchBezier.Tpo patch/$(DEPDIR)/darkradiant-PatchBezier.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='patch/PatchBezier.cpp' object='patch/darkradiant-PatchBezier.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o patch/darkradiant-PatchBezier.o `test -f 'patch/PatchBezier.cpp' || echo '$(srcdir)/'`patch/PatchBezier.cpp
-
-patch/darkradiant-PatchBezier.obj: patch/PatchBezier.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT patch/darkradiant-PatchBezier.obj -MD -MP -MF patch/$(DEPDIR)/darkradiant-PatchBezier.Tpo -c -o patch/darkradiant-PatchBezier.obj `if test -f 'patch/PatchBezier.cpp'; then $(CYGPATH_W) 'patch/PatchBezier.cpp'; else $(CYGPATH_W) '$(srcdir)/patch/PatchBezier.cpp'; fi`
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) patch/$(DEPDIR)/darkradiant-PatchBezier.Tpo patch/$(DEPDIR)/darkradiant-PatchBezier.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='patch/PatchBezier.cpp' object='patch/darkradiant-PatchBezier.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o patch/darkradiant-PatchBezier.obj `if test -f 'patch/PatchBezier.cpp'; then $(CYGPATH_W) 'patch/PatchBezier.cpp'; else $(CYGPATH_W) '$(srcdir)/patch/PatchBezier.cpp'; fi`
-
patch/darkradiant-PatchRenderables.o: patch/PatchRenderables.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT patch/darkradiant-PatchRenderables.o -MD -MP -MF patch/$(DEPDIR)/darkradiant-PatchRenderables.Tpo -c -o patch/darkradiant-PatchRenderables.o `test -f 'patch/PatchRenderables.cpp' || echo '$(srcdir)/'`patch/PatchRenderables.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) patch/$(DEPDIR)/darkradiant-PatchRenderables.Tpo patch/$(DEPDIR)/darkradiant-PatchRenderables.Po
@@ -4997,19 +5172,47 @@ map/darkradiant-FindMapElements.obj: map/FindMapElements.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-FindMapElements.obj `if test -f 'map/FindMapElements.cpp'; then $(CYGPATH_W) 'map/FindMapElements.cpp'; else $(CYGPATH_W) '$(srcdir)/map/FindMapElements.cpp'; fi`
-map/darkradiant-InfoFile.o: map/InfoFile.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-InfoFile.o -MD -MP -MF map/$(DEPDIR)/darkradiant-InfoFile.Tpo -c -o map/darkradiant-InfoFile.o `test -f 'map/InfoFile.cpp' || echo '$(srcdir)/'`map/InfoFile.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-InfoFile.Tpo map/$(DEPDIR)/darkradiant-InfoFile.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/InfoFile.cpp' object='map/darkradiant-InfoFile.o' libtool=no @AMDEPBACKSLASH@
+map/infofile/darkradiant-InfoFileManager.o: map/infofile/InfoFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFileManager.o -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Tpo -c -o map/infofile/darkradiant-InfoFileManager.o `test -f 'map/infofile/InfoFileManager.cpp' || echo '$(srcdir)/'`map/infofile/InfoFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFileManager.cpp' object='map/infofile/darkradiant-InfoFileManager.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFileManager.o `test -f 'map/infofile/InfoFileManager.cpp' || echo '$(srcdir)/'`map/infofile/InfoFileManager.cpp
+
+map/infofile/darkradiant-InfoFileManager.obj: map/infofile/InfoFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFileManager.obj -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Tpo -c -o map/infofile/darkradiant-InfoFileManager.obj `if test -f 'map/infofile/InfoFileManager.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFileManager.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFileManager.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFileManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFileManager.cpp' object='map/infofile/darkradiant-InfoFileManager.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFileManager.obj `if test -f 'map/infofile/InfoFileManager.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFileManager.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFileManager.cpp'; fi`
+
+map/infofile/darkradiant-InfoFile.o: map/infofile/InfoFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFile.o -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFile.Tpo -c -o map/infofile/darkradiant-InfoFile.o `test -f 'map/infofile/InfoFile.cpp' || echo '$(srcdir)/'`map/infofile/InfoFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFile.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFile.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFile.cpp' object='map/infofile/darkradiant-InfoFile.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFile.o `test -f 'map/infofile/InfoFile.cpp' || echo '$(srcdir)/'`map/infofile/InfoFile.cpp
+
+map/infofile/darkradiant-InfoFile.obj: map/infofile/InfoFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFile.obj -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFile.Tpo -c -o map/infofile/darkradiant-InfoFile.obj `if test -f 'map/infofile/InfoFile.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFile.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFile.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFile.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFile.cpp' object='map/infofile/darkradiant-InfoFile.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFile.obj `if test -f 'map/infofile/InfoFile.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFile.cpp'; fi`
+
+map/infofile/darkradiant-InfoFileExporter.o: map/infofile/InfoFileExporter.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFileExporter.o -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo -c -o map/infofile/darkradiant-InfoFileExporter.o `test -f 'map/infofile/InfoFileExporter.cpp' || echo '$(srcdir)/'`map/infofile/InfoFileExporter.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFileExporter.cpp' object='map/infofile/darkradiant-InfoFileExporter.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-InfoFile.o `test -f 'map/InfoFile.cpp' || echo '$(srcdir)/'`map/InfoFile.cpp
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFileExporter.o `test -f 'map/infofile/InfoFileExporter.cpp' || echo '$(srcdir)/'`map/infofile/InfoFileExporter.cpp
-map/darkradiant-InfoFile.obj: map/InfoFile.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-InfoFile.obj -MD -MP -MF map/$(DEPDIR)/darkradiant-InfoFile.Tpo -c -o map/darkradiant-InfoFile.obj `if test -f 'map/InfoFile.cpp'; then $(CYGPATH_W) 'map/InfoFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/InfoFile.cpp'; fi`
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-InfoFile.Tpo map/$(DEPDIR)/darkradiant-InfoFile.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/InfoFile.cpp' object='map/darkradiant-InfoFile.obj' libtool=no @AMDEPBACKSLASH@
+map/infofile/darkradiant-InfoFileExporter.obj: map/infofile/InfoFileExporter.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/infofile/darkradiant-InfoFileExporter.obj -MD -MP -MF map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo -c -o map/infofile/darkradiant-InfoFileExporter.obj `if test -f 'map/infofile/InfoFileExporter.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFileExporter.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFileExporter.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo map/infofile/$(DEPDIR)/darkradiant-InfoFileExporter.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/infofile/InfoFileExporter.cpp' object='map/infofile/darkradiant-InfoFileExporter.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-InfoFile.obj `if test -f 'map/InfoFile.cpp'; then $(CYGPATH_W) 'map/InfoFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/InfoFile.cpp'; fi`
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/infofile/darkradiant-InfoFileExporter.obj `if test -f 'map/infofile/InfoFileExporter.cpp'; then $(CYGPATH_W) 'map/infofile/InfoFileExporter.cpp'; else $(CYGPATH_W) '$(srcdir)/map/infofile/InfoFileExporter.cpp'; fi`
map/darkradiant-MapFileManager.o: map/MapFileManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-MapFileManager.o -MD -MP -MF map/$(DEPDIR)/darkradiant-MapFileManager.Tpo -c -o map/darkradiant-MapFileManager.o `test -f 'map/MapFileManager.cpp' || echo '$(srcdir)/'`map/MapFileManager.cpp
@@ -5095,20 +5298,6 @@ map/algorithm/darkradiant-MapImporter.obj: map/algorithm/MapImporter.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/algorithm/darkradiant-MapImporter.obj `if test -f 'map/algorithm/MapImporter.cpp'; then $(CYGPATH_W) 'map/algorithm/MapImporter.cpp'; else $(CYGPATH_W) '$(srcdir)/map/algorithm/MapImporter.cpp'; fi`
-map/algorithm/darkradiant-InfoFileExporter.o: map/algorithm/InfoFileExporter.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/algorithm/darkradiant-InfoFileExporter.o -MD -MP -MF map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo -c -o map/algorithm/darkradiant-InfoFileExporter.o `test -f 'map/algorithm/InfoFileExporter.cpp' || echo '$(srcdir)/'`map/algorithm/InfoFileExporter.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/algorithm/InfoFileExporter.cpp' object='map/algorithm/darkradiant-InfoFileExporter.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/algorithm/darkradiant-InfoFileExporter.o `test -f 'map/algorithm/InfoFileExporter.cpp' || echo '$(srcdir)/'`map/algorithm/InfoFileExporter.cpp
-
-map/algorithm/darkradiant-InfoFileExporter.obj: map/algorithm/InfoFileExporter.cpp
- at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/algorithm/darkradiant-InfoFileExporter.obj -MD -MP -MF map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo -c -o map/algorithm/darkradiant-InfoFileExporter.obj `if test -f 'map/algorithm/InfoFileExporter.cpp'; then $(CYGPATH_W) 'map/algorithm/InfoFileExporter.cpp'; else $(CYGPATH_W) '$(srcdir)/map/algorithm/InfoFileExporter.cpp'; fi`
- at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Tpo map/algorithm/$(DEPDIR)/darkradiant-InfoFileExporter.Po
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/algorithm/InfoFileExporter.cpp' object='map/algorithm/darkradiant-InfoFileExporter.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/algorithm/darkradiant-InfoFileExporter.obj `if test -f 'map/algorithm/InfoFileExporter.cpp'; then $(CYGPATH_W) 'map/algorithm/InfoFileExporter.cpp'; else $(CYGPATH_W) '$(srcdir)/map/algorithm/InfoFileExporter.cpp'; fi`
-
map/darkradiant-CounterManager.o: map/CounterManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-CounterManager.o -MD -MP -MF map/$(DEPDIR)/darkradiant-CounterManager.Tpo -c -o map/darkradiant-CounterManager.o `test -f 'map/CounterManager.cpp' || echo '$(srcdir)/'`map/CounterManager.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-CounterManager.Tpo map/$(DEPDIR)/darkradiant-CounterManager.Po
@@ -5249,6 +5438,34 @@ map/darkradiant-MapFormatManager.obj: map/MapFormatManager.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-MapFormatManager.obj `if test -f 'map/MapFormatManager.cpp'; then $(CYGPATH_W) 'map/MapFormatManager.cpp'; else $(CYGPATH_W) '$(srcdir)/map/MapFormatManager.cpp'; fi`
+map/darkradiant-AasFileManager.o: map/AasFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-AasFileManager.o -MD -MP -MF map/$(DEPDIR)/darkradiant-AasFileManager.Tpo -c -o map/darkradiant-AasFileManager.o `test -f 'map/AasFileManager.cpp' || echo '$(srcdir)/'`map/AasFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-AasFileManager.Tpo map/$(DEPDIR)/darkradiant-AasFileManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/AasFileManager.cpp' object='map/darkradiant-AasFileManager.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-AasFileManager.o `test -f 'map/AasFileManager.cpp' || echo '$(srcdir)/'`map/AasFileManager.cpp
+
+map/darkradiant-AasFileManager.obj: map/AasFileManager.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-AasFileManager.obj -MD -MP -MF map/$(DEPDIR)/darkradiant-AasFileManager.Tpo -c -o map/darkradiant-AasFileManager.obj `if test -f 'map/AasFileManager.cpp'; then $(CYGPATH_W) 'map/AasFileManager.cpp'; else $(CYGPATH_W) '$(srcdir)/map/AasFileManager.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-AasFileManager.Tpo map/$(DEPDIR)/darkradiant-AasFileManager.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/AasFileManager.cpp' object='map/darkradiant-AasFileManager.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-AasFileManager.obj `if test -f 'map/AasFileManager.cpp'; then $(CYGPATH_W) 'map/AasFileManager.cpp'; else $(CYGPATH_W) '$(srcdir)/map/AasFileManager.cpp'; fi`
+
+map/darkradiant-RenderableAasFile.o: map/RenderableAasFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-RenderableAasFile.o -MD -MP -MF map/$(DEPDIR)/darkradiant-RenderableAasFile.Tpo -c -o map/darkradiant-RenderableAasFile.o `test -f 'map/RenderableAasFile.cpp' || echo '$(srcdir)/'`map/RenderableAasFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-RenderableAasFile.Tpo map/$(DEPDIR)/darkradiant-RenderableAasFile.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/RenderableAasFile.cpp' object='map/darkradiant-RenderableAasFile.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-RenderableAasFile.o `test -f 'map/RenderableAasFile.cpp' || echo '$(srcdir)/'`map/RenderableAasFile.cpp
+
+map/darkradiant-RenderableAasFile.obj: map/RenderableAasFile.cpp
+ at am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT map/darkradiant-RenderableAasFile.obj -MD -MP -MF map/$(DEPDIR)/darkradiant-RenderableAasFile.Tpo -c -o map/darkradiant-RenderableAasFile.obj `if test -f 'map/RenderableAasFile.cpp'; then $(CYGPATH_W) 'map/RenderableAasFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/RenderableAasFile.cpp'; fi`
+ at am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) map/$(DEPDIR)/darkradiant-RenderableAasFile.Tpo map/$(DEPDIR)/darkradiant-RenderableAasFile.Po
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='map/RenderableAasFile.cpp' object='map/darkradiant-RenderableAasFile.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCXX_FALSE@ $(AM_V_CXX at am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o map/darkradiant-RenderableAasFile.obj `if test -f 'map/RenderableAasFile.cpp'; then $(CYGPATH_W) 'map/RenderableAasFile.cpp'; else $(CYGPATH_W) '$(srcdir)/map/RenderableAasFile.cpp'; fi`
+
clipper/darkradiant-ClipPoint.o: clipper/ClipPoint.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(darkradiant_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT clipper/darkradiant-ClipPoint.o -MD -MP -MF clipper/$(DEPDIR)/darkradiant-ClipPoint.Tpo -c -o clipper/darkradiant-ClipPoint.o `test -f 'clipper/ClipPoint.cpp' || echo '$(srcdir)/'`clipper/ClipPoint.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) clipper/$(DEPDIR)/darkradiant-ClipPoint.Tpo clipper/$(DEPDIR)/darkradiant-ClipPoint.Po
@@ -5724,6 +5941,8 @@ distclean-generic:
-rm -f map/$(am__dirstamp)
-rm -f map/algorithm/$(DEPDIR)/$(am__dirstamp)
-rm -f map/algorithm/$(am__dirstamp)
+ -rm -f map/infofile/$(DEPDIR)/$(am__dirstamp)
+ -rm -f map/infofile/$(am__dirstamp)
-rm -f modulesystem/$(DEPDIR)/$(am__dirstamp)
-rm -f modulesystem/$(am__dirstamp)
-rm -f namespace/$(DEPDIR)/$(am__dirstamp)
@@ -5748,6 +5967,8 @@ distclean-generic:
-rm -f selection/algorithm/$(am__dirstamp)
-rm -f selection/clipboard/$(DEPDIR)/$(am__dirstamp)
-rm -f selection/clipboard/$(am__dirstamp)
+ -rm -f selection/group/$(DEPDIR)/$(am__dirstamp)
+ -rm -f selection/group/$(am__dirstamp)
-rm -f selection/selectionset/$(DEPDIR)/$(am__dirstamp)
-rm -f selection/selectionset/$(am__dirstamp)
-rm -f selection/shaderclipboard/$(DEPDIR)/$(am__dirstamp)
@@ -5760,6 +5981,8 @@ distclean-generic:
-rm -f textool/$(am__dirstamp)
-rm -f textool/item/$(DEPDIR)/$(am__dirstamp)
-rm -f textool/item/$(am__dirstamp)
+ -rm -f ui/aas/$(DEPDIR)/$(am__dirstamp)
+ -rm -f ui/aas/$(am__dirstamp)
-rm -f ui/about/$(DEPDIR)/$(am__dirstamp)
-rm -f ui/about/$(am__dirstamp)
-rm -f ui/animationpreview/$(DEPDIR)/$(am__dirstamp)
@@ -5830,7 +6053,7 @@ clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
clean-libtool mostlyclean-am
distclean: distclean-am
- -rm -rf ./$(DEPDIR) brush/$(DEPDIR) brush/csg/$(DEPDIR) brush/export/$(DEPDIR) camera/$(DEPDIR) clipper/$(DEPDIR) layers/$(DEPDIR) log/$(DEPDIR) map/$(DEPDIR) map/algorithm/$(DEPDIR) modulesystem/$(DEPDIR) namespace/$(DEPDIR) patch/$(DEPDIR) patch/algorithm/$(DEPDIR) referencecache/$(DEPDIR) render/$(DEPDIR) render/backend/$(DEPDIR) render/backend/glprogram/$(DEPDIR) render/debug/$(DEPDIR) selection/$(DEPDIR) selection/algorithm/$(DEPDIR) selection/clipboard/$(DEPDIR) selection/selectio [...]
+ -rm -rf ./$(DEPDIR) brush/$(DEPDIR) brush/csg/$(DEPDIR) brush/export/$(DEPDIR) camera/$(DEPDIR) clipper/$(DEPDIR) layers/$(DEPDIR) log/$(DEPDIR) map/$(DEPDIR) map/algorithm/$(DEPDIR) map/infofile/$(DEPDIR) modulesystem/$(DEPDIR) namespace/$(DEPDIR) patch/$(DEPDIR) patch/algorithm/$(DEPDIR) referencecache/$(DEPDIR) render/$(DEPDIR) render/backend/$(DEPDIR) render/backend/glprogram/$(DEPDIR) render/debug/$(DEPDIR) selection/$(DEPDIR) selection/algorithm/$(DEPDIR) selection/clipboard/$(DEP [...]
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -5876,7 +6099,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR) brush/$(DEPDIR) brush/csg/$(DEPDIR) brush/export/$(DEPDIR) camera/$(DEPDIR) clipper/$(DEPDIR) layers/$(DEPDIR) log/$(DEPDIR) map/$(DEPDIR) map/algorithm/$(DEPDIR) modulesystem/$(DEPDIR) namespace/$(DEPDIR) patch/$(DEPDIR) patch/algorithm/$(DEPDIR) referencecache/$(DEPDIR) render/$(DEPDIR) render/backend/$(DEPDIR) render/backend/glprogram/$(DEPDIR) render/debug/$(DEPDIR) selection/$(DEPDIR) selection/algorithm/$(DEPDIR) selection/clipboard/$(DEPDIR) selection/selectio [...]
+ -rm -rf ./$(DEPDIR) brush/$(DEPDIR) brush/csg/$(DEPDIR) brush/export/$(DEPDIR) camera/$(DEPDIR) clipper/$(DEPDIR) layers/$(DEPDIR) log/$(DEPDIR) map/$(DEPDIR) map/algorithm/$(DEPDIR) map/infofile/$(DEPDIR) modulesystem/$(DEPDIR) namespace/$(DEPDIR) patch/$(DEPDIR) patch/algorithm/$(DEPDIR) referencecache/$(DEPDIR) render/$(DEPDIR) render/backend/$(DEPDIR) render/backend/glprogram/$(DEPDIR) render/debug/$(DEPDIR) selection/$(DEPDIR) selection/algorithm/$(DEPDIR) selection/clipboard/$(DEP [...]
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/radiant/RadiantModule.cpp b/radiant/RadiantModule.cpp
index 0a37d83..1706115 100644
--- a/radiant/RadiantModule.cpp
+++ b/radiant/RadiantModule.cpp
@@ -19,7 +19,6 @@
#include "scene/Node.h"
-#include "map/AutoSaver.h"
#include "map/PointFile.h"
#include "ui/texturebrowser/TextureBrowser.h"
#include "ui/mediabrowser/MediaBrowser.h"
@@ -43,6 +42,7 @@
#include "ui/surfaceinspector/SurfaceInspector.h"
#include "ui/transform/TransformDialog.h"
#include "ui/mapinfo/MapInfoDialog.h"
+#include "ui/layers/LayerControlDialog.h"
#include "ui/animationpreview/MD5AnimationViewer.h"
#include "ui/commandlist/CommandList.h"
#include "ui/findshader/FindShader.h"
@@ -52,6 +52,7 @@
#include "map/FindMapElements.h"
#include "ui/modelselector/ModelSelector.h"
#include "EventRateLimiter.h"
+#include "selection/shaderclipboard/ShaderClipboard.h"
#include <wx/app.h>
@@ -207,7 +208,6 @@ void RadiantModule::initialiseModule(const ApplicationContext& ctx)
ui::TexTool::registerCommands();
ui::MediaBrowser::registerCommandsAndPreferences();
- map::AutoSaver().init();
selection::algorithm::registerCommands();
brush::algorithm::registerCommands();
@@ -234,9 +234,10 @@ void RadiantModule::shutdownModule()
void RadiantModule::postModuleInitialisation()
{
// Create the empty Settings node and set the title to empty.
- ui::PrefDialog::Instance().createOrFindPage(_("Game"));
- ui::PrefPagePtr settingsPage = ui::PrefDialog::Instance().createOrFindPage(_("Settings"));
- settingsPage->setTitle("");
+ GlobalPreferenceSystem().getPage(_("Game"));
+
+ IPreferencePage& settingsPage = GlobalPreferenceSystem().getPage(_("Settings"));
+ settingsPage.setTitle("");
// Construct the MRU commands and menu structure, load the recently used files
GlobalMRU().initialise();
@@ -249,6 +250,11 @@ void RadiantModule::postModuleInitialisation()
// Initialise the mainframe
GlobalMainFrame().construct();
+ // Initialise the shaderclipboard
+ GlobalShaderClipboard().clear();
+
+ ui::LayerControlDialog::init();
+
// Broadcast the startup event
broadcastStartupEvent();
@@ -258,6 +264,9 @@ void RadiantModule::postModuleInitialisation()
// Pre-load models
ui::ModelSelector::Populate();
+ // Show the top level window as late as possible
+ GlobalMainFrame().getWxTopLevelWindow()->Show();
+
time_t localtime;
time(&localtime);
rMessage() << "Startup complete at " << ctime(&localtime) << std::endl;
@@ -266,7 +275,7 @@ void RadiantModule::postModuleInitialisation()
void RadiantModule::registerUICommands()
{
GlobalCommandSystem().addCommand("ProjectSettings", ui::PrefDialog::ShowProjectSettings);
- GlobalCommandSystem().addCommand("Preferences", ui::PrefDialog::ShowDialog);
+ GlobalCommandSystem().addCommand("Preferences", ui::PrefDialog::ShowPrefDialog);
GlobalCommandSystem().addCommand("ToggleConsole", ui::Console::toggle);
GlobalCommandSystem().addCommand("ToggleLightInspector", ui::LightInspector::toggleInspector);
diff --git a/radiant/RadiantModule.h b/radiant/RadiantModule.h
index d9846be..8335852 100644
--- a/radiant/RadiantModule.h
+++ b/radiant/RadiantModule.h
@@ -17,7 +17,7 @@ class RadiantModule :
// Our signals
sigc::signal<void> _radiantStarted;
sigc::signal<void> _radiantShutdown;
-
+
// Thread manager instance
mutable std::unique_ptr<RadiantThreadManager> _threadManager;
@@ -30,8 +30,9 @@ public:
void broadcastStartupEvent();
// IRadiant implementation
- sigc::signal<void> signal_radiantStarted() const;
- sigc::signal<void> signal_radiantShutdown() const;
+ sigc::signal<void> signal_radiantStarted() const override;
+ sigc::signal<void> signal_radiantShutdown() const override;
+
ThreadManager& getThreadManager();
void performLongRunningOperation(
const std::function<void(ILongRunningOperation&)>& operationFunc,
diff --git a/radiant/brush/Brush.cpp b/radiant/brush/Brush.cpp
index 666a6cb..664d80e 100644
--- a/radiant/brush/Brush.cpp
+++ b/radiant/brush/Brush.cpp
@@ -1094,8 +1094,9 @@ bool Brush::buildWindings() {
// update brush bounds
const Winding& winding = f.getWinding();
- for (Winding::const_iterator i = winding.begin(); i != winding.end(); ++i) {
- m_aabb_local.includePoint(i->vertex);
+ for (const WindingVertex& wv : winding)
+ {
+ m_aabb_local.includePoint(wv.vertex);
}
// update texture coordinates
diff --git a/radiant/brush/BrushModule.cpp b/radiant/brush/BrushModule.cpp
index 53c22b2..c13381d 100644
--- a/radiant/brush/BrushModule.cpp
+++ b/radiant/brush/BrushModule.cpp
@@ -24,14 +24,14 @@
void BrushModuleImpl::constructPreferences()
{
// Add a page to the given group
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Primitives"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Primitives"));
// Add the default texture scale preference and connect it to the according registryKey
// Note: this should be moved somewhere else, I think
- page->appendEntry(_("Default texture scale"), "user/ui/textures/defaultTextureScale");
+ page.appendEntry(_("Default texture scale"), "user/ui/textures/defaultTextureScale");
// The checkbox to enable/disable the texture lock option
- page->appendCheckBox("", _("Enable Texture Lock (for Brushes)"), "user/ui/brush/textureLock");
+ page.appendCheckBox(_("Enable Texture Lock (for Brushes)"), "user/ui/brush/textureLock");
}
void BrushModuleImpl::construct()
diff --git a/radiant/brush/BrushNode.cpp b/radiant/brush/BrushNode.cpp
index 24a9d03..d74f037 100644
--- a/radiant/brush/BrushNode.cpp
+++ b/radiant/brush/BrushNode.cpp
@@ -82,44 +82,6 @@ void BrushNode::snapComponents(float snap) {
}
}
-void BrushNode::invertSelected()
-{
- // Override default behaviour of SelectableNode, we have components
-
- // Check if we are in component mode or not
- if (GlobalSelectionSystem().Mode() == SelectionSystem::ePrimitive)
- {
- // Non-component mode, invert the selection of the whole brush
- SelectableNode::invertSelected();
- }
- else
- {
- // Component mode, invert the component selection
- switch (GlobalSelectionSystem().ComponentMode()) {
- case SelectionSystem::eVertex:
- for (VertexInstances::iterator i = m_vertexInstances.begin(); i != m_vertexInstances.end(); ++i)
- {
- i->invertSelected();
- }
- break;
- case SelectionSystem::eEdge:
- for (EdgeInstances::iterator i = m_edgeInstances.begin(); i != m_edgeInstances.end(); ++i)
- {
- i->invertSelected();
- }
- break;
- case SelectionSystem::eFace:
- for (FaceInstances::iterator i = m_faceInstances.begin(); i != m_faceInstances.end(); ++i)
- {
- i->invertSelected();
- }
- break;
- case SelectionSystem::eDefault:
- break;
- } // switch
- }
-}
-
void BrushNode::testSelect(Selector& selector, SelectionTest& test) {
test.BeginMesh(localToWorld());
@@ -152,6 +114,34 @@ void BrushNode::setSelectedComponents(bool select, SelectionSystem::EComponentMo
}
}
+void BrushNode::invertSelectedComponents(SelectionSystem::EComponentMode mode)
+{
+ // Component mode, invert the component selection
+ switch (mode)
+ {
+ case SelectionSystem::eVertex:
+ for (brush::VertexInstance& vertex : m_vertexInstances)
+ {
+ vertex.invertSelected();
+ }
+ break;
+ case SelectionSystem::eEdge:
+ for (EdgeInstance& edge : m_edgeInstances)
+ {
+ edge.invertSelected();
+ }
+ break;
+ case SelectionSystem::eFace:
+ for (FaceInstance& face : m_faceInstances)
+ {
+ face.invertSelected();
+ }
+ break;
+ case SelectionSystem::eDefault:
+ break;
+ } // switch
+}
+
void BrushNode::testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) {
test.BeginMesh(localToWorld());
@@ -217,7 +207,7 @@ void BrushNode::selectReversedPlanes(Selector& selector, const SelectedPlanes& s
}
}
-void BrushNode::selectedChangedComponent(const Selectable& selectable)
+void BrushNode::selectedChangedComponent(const ISelectable& selectable)
{
_renderableComponentsNeedUpdate = true;
@@ -393,9 +383,11 @@ void BrushNode::viewChanged() const {
m_viewChanged = true;
}
-bool BrushNode::isHighlighted() const
+std::size_t BrushNode::getHighlightFlags()
{
- return isSelected();
+ if (!isSelected()) return Highlight::NoHighlight;
+
+ return isGroupMember() ? (Highlight::Selected | Highlight::GroupMember) : Highlight::Selected;
}
void BrushNode::evaluateViewDependent(const VolumeTest& volume, const Matrix4& localToWorld) const
@@ -412,6 +404,7 @@ void BrushNode::evaluateViewDependent(const VolumeTest& volume, const Matrix4& l
std::size_t numVisibleFaces(0);
bool* j = faces_visible;
+ bool forceVisible = isForcedVisible();
// Iterator to an index of a visible face
std::size_t* visibleFaceIter = visibleFaceIndices;
@@ -423,7 +416,7 @@ void BrushNode::evaluateViewDependent(const VolumeTest& volume, const Matrix4& l
{
// Check if face is filtered before adding to visibility matrix
// greebo: Removed localToWorld transformation here, brushes don't have a non-identity l2w
- if (i->faceIsVisible() && i->intersectVolume(volume))
+ if (forceVisible || (i->faceIsVisible() && i->intersectVolume(volume)))
{
*j = true;
@@ -449,13 +442,16 @@ void BrushNode::renderSolid(RenderableCollector& collector,
assert(_renderEntity); // brushes rendered without parent entity - no way!
+ // Check for the override status of this brush
+ bool forceVisible = isForcedVisible();
+
// Submit the lights and renderable geometry for each face
for (FaceInstances::const_iterator i = m_faceInstances.begin();
i != m_faceInstances.end();
++i)
{
// Skip invisible faces before traversing further
- if (!i->faceIsVisible()) continue;
+ if (!forceVisible && !i->faceIsVisible()) continue;
collector.setLights(i->m_lights);
@@ -502,7 +498,7 @@ void BrushNode::renderSelectedPoints(RenderableCollector& collector,
update_selected();
if (!_selectedPoints.empty())
{
- collector.highlightPrimitives(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
collector.SetState(BrushNode::m_state_selpoint, RenderableCollector::eWireframeOnly);
collector.SetState(BrushNode::m_state_selpoint, RenderableCollector::eFullMaterials);
collector.addRenderable(_selectedPoints, localToWorld);
diff --git a/radiant/brush/BrushNode.h b/radiant/brush/BrushNode.h
index 0cabf92..c681a88 100644
--- a/radiant/brush/BrushNode.h
+++ b/radiant/brush/BrushNode.h
@@ -6,7 +6,7 @@
#include "iscenegraph.h"
#include "Brush.h"
-#include "SelectableNode.h"
+#include "scene/SelectableNode.h"
#include "FaceInstance.h"
#include "EdgeInstance.h"
#include "VertexInstance.h"
@@ -88,16 +88,14 @@ public:
// Bounded implementation
virtual const AABB& localAABB() const;
- // Override ObservedSelectable implementation
- virtual void invertSelected();
-
// SelectionTestable implementation
virtual void testSelect(Selector& selector, SelectionTest& test);
// ComponentSelectionTestable
- bool isSelectedComponents() const;
- void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode);
- void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode);
+ bool isSelectedComponents() const override;
+ void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) override;
+ void invertSelectedComponents(SelectionSystem::EComponentMode mode) override;
+ void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) override;
// override scene::Inode::onRemoveFromScene to deselect the child components
virtual void onInsertIntoScene(scene::IMapRootNode& root) override;
@@ -106,7 +104,7 @@ public:
// ComponentEditable implementation
const AABB& getSelectedComponentsBounds() const;
- void selectedChangedComponent(const Selectable& selectable);
+ void selectedChangedComponent(const ISelectable& selectable);
// PlaneSelectable implementation
void selectPlanes(Selector& selector, SelectionTest& test, const PlaneCallback& selectedPlaneCallback);
@@ -143,13 +141,13 @@ public:
void clearLights();
// Renderable implementation
- void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- void viewChanged() const;
- bool isHighlighted() const;
+ void viewChanged() const override;
+ std::size_t getHighlightFlags() override;
void evaluateTransform();
diff --git a/radiant/brush/EdgeInstance.h b/radiant/brush/EdgeInstance.h
index 422f383..4f3cf39 100644
--- a/radiant/brush/EdgeInstance.h
+++ b/radiant/brush/EdgeInstance.h
@@ -3,7 +3,7 @@
#include "FaceInstance.h"
-class EdgeInstance : public Selectable {
+class EdgeInstance : public ISelectable {
FaceInstances& m_faceInstances;
SelectableEdge* m_edge;
diff --git a/radiant/brush/FaceInstance.cpp b/radiant/brush/FaceInstance.cpp
index aef1966..e15a581 100644
--- a/radiant/brush/FaceInstance.cpp
+++ b/radiant/brush/FaceInstance.cpp
@@ -56,7 +56,7 @@ const Face& FaceInstance::getFace() const {
return *m_face;
}
-void FaceInstance::selectedChanged(const Selectable& selectable)
+void FaceInstance::selectedChanged(const ISelectable& selectable)
{
if (selectable.isSelected())
{
@@ -133,7 +133,7 @@ void FaceInstance::setSelected(SelectionSystem::EComponentMode mode, bool select
void FaceInstance::invertSelected() {
switch (GlobalSelectionSystem().ComponentMode()) {
case SelectionSystem::eFace:
- m_selectable.invertSelected();
+ m_selectable.setSelected(!m_selectable.isSelected());
break;
case SelectionSystem::eVertex:
break;
@@ -173,7 +173,7 @@ void FaceInstance::submitRenderables(RenderableCollector& collector,
if (selectedComponents())
{
- collector.highlightFaces(true);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, true);
}
m_face->submitRenderables(collector, Matrix4::getIdentity(), entity);
@@ -193,7 +193,7 @@ void FaceInstance::submitRenderables(RenderableCollector& collector,
if (selectedComponents())
{
- collector.highlightFaces(true);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, true);
}
m_face->submitRenderables(collector, localToWorld, entity);
diff --git a/radiant/brush/FaceInstance.h b/radiant/brush/FaceInstance.h
index 3c2a8ec..d104fe9 100644
--- a/radiant/brush/FaceInstance.h
+++ b/radiant/brush/FaceInstance.h
@@ -44,7 +44,7 @@ public:
const Face& getFace() const;
- void selectedChanged(const Selectable& selectable);
+ void selectedChanged(const ISelectable& selectable);
bool selectedVertices() const;
bool selectedEdges() const;
diff --git a/radiant/brush/TextureProjection.cpp b/radiant/brush/TextureProjection.cpp
index 29f9f32..bbce582 100644
--- a/radiant/brush/TextureProjection.cpp
+++ b/radiant/brush/TextureProjection.cpp
@@ -200,12 +200,12 @@ void TextureProjection::fitTexture(std::size_t width, std::size_t height, const
AABB perfect(Vector3(s_repeat * 0.5, t_repeat * 0.5, 0), Vector3(s_repeat * 0.5, t_repeat * 0.5, 1));
// the difference between the current texture transform and the perfectly fitted transform
- Matrix4 matrix = Matrix4::getTranslation(bounds.origin - perfect.origin);
- matrix.scaleBy(bounds.extents / perfect.extents, perfect.origin);
- matrix.invert();
+ Matrix4 diffMatrix = Matrix4::getTranslation(bounds.origin - perfect.origin);
+ diffMatrix.scaleBy(bounds.extents / perfect.extents, perfect.origin);
+ diffMatrix.invert();
// apply the difference to the current texture transform
- st2tex.premultiplyBy(matrix);
+ st2tex.premultiplyBy(diffMatrix);
setTransform((float)width, (float)height, st2tex);
normalise((float)width, (float)height);
diff --git a/radiant/brush/VertexInstance.h b/radiant/brush/VertexInstance.h
index be0405e..4390025 100644
--- a/radiant/brush/VertexInstance.h
+++ b/radiant/brush/VertexInstance.h
@@ -6,7 +6,7 @@
namespace brush {
class VertexInstance :
- public Selectable
+ public ISelectable
{
FaceInstances& m_faceInstances;
SelectableVertex* m_vertex;
diff --git a/radiant/brush/csg/CSG.cpp b/radiant/brush/csg/CSG.cpp
index 368471e..e0ea44d 100644
--- a/radiant/brush/csg/CSG.cpp
+++ b/radiant/brush/csg/CSG.cpp
@@ -323,8 +323,8 @@ void subtractBrushesFromUnselected(const cmd::ArgumentList& args)
// greebo: TODO: Make this a member method of the Brush class
bool Brush_merge(Brush& brush, const BrushPtrVector& in, bool onlyshape) {
// gather potential outer faces
- typedef std::vector<const Face*> Faces;
- Faces faces;
+ typedef std::vector<const Face*> FaceList;
+ FaceList faces;
for (BrushPtrVector::const_iterator i(in.begin()); i != in.end(); ++i) {
(*i)->getBrush().evaluateBRep();
@@ -356,7 +356,7 @@ bool Brush_merge(Brush& brush, const BrushPtrVector& in, bool onlyshape) {
}
// check faces already stored
- for (Faces::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m) {
+ for (FaceList::const_iterator m = faces.begin(); !skip && m != faces.end(); ++m) {
const Face& face2 = *(*m);
// face equals another face
@@ -388,7 +388,7 @@ bool Brush_merge(Brush& brush, const BrushPtrVector& in, bool onlyshape) {
}
}
- for (Faces::const_iterator i = faces.begin(); i != faces.end(); ++i) {
+ for (FaceList::const_iterator i = faces.begin(); i != faces.end(); ++i) {
if (!brush.addFace(*(*i))) {
// result would have too many sides
return false;
diff --git a/radiant/camera/CamRenderer.cpp b/radiant/camera/CamRenderer.cpp
index 2819e6e..9195ab8 100644
--- a/radiant/camera/CamRenderer.cpp
+++ b/radiant/camera/CamRenderer.cpp
@@ -44,14 +44,17 @@ void CamRenderer::PopState()
_stateStack.pop_back();
}
-void CamRenderer::highlightFaces(bool enable)
+void CamRenderer::setHighlightFlag(Highlight::Flags flags, bool enabled)
{
- _stateStack.back().highlightFaces = enable;
-}
-
-void CamRenderer::highlightPrimitives(bool enable)
-{
- _stateStack.back().highlightPrimitives = enable;
+ if (flags & Highlight::Faces)
+ {
+ _stateStack.back().highlightFaces = enabled;
+ }
+
+ if (flags & Highlight::Primitives)
+ {
+ _stateStack.back().highlightPrimitives = enabled;
+ }
}
void CamRenderer::setLights(const LightList& lights)
diff --git a/radiant/camera/CamRenderer.h b/radiant/camera/CamRenderer.h
index bb50e87..dbb393a 100644
--- a/radiant/camera/CamRenderer.h
+++ b/radiant/camera/CamRenderer.h
@@ -51,8 +51,7 @@ public:
bool supportsFullMaterials() const;
void PushState();
void PopState();
- void highlightFaces(bool enable = true);
- void highlightPrimitives(bool enable = true);
+ void setHighlightFlag(Highlight::Flags flags, bool enabled) override;
void setLights(const LightList& lights);
void addRenderable(const OpenGLRenderable& renderable, const Matrix4& world);
void addRenderable(const OpenGLRenderable& renderable,
diff --git a/radiant/camera/CamWnd.cpp b/radiant/camera/CamWnd.cpp
index cf9c9cd..96787a5 100644
--- a/radiant/camera/CamWnd.cpp
+++ b/radiant/camera/CamWnd.cpp
@@ -149,17 +149,12 @@ CamWnd::CamWnd(wxWindow* parent) :
_freeMoveEnabled(false),
_wxGLWidget(new wxutil::GLWidget(_mainWxWidget, std::bind(&CamWnd::onRender, this), "CamWnd")),
_timer(this),
- _timerLock(false),
- _deferredDraw(std::bind(&CamWnd::performDeferredDraw, this))
+ _timerLock(false)
{
Connect(wxEVT_TIMER, wxTimerEventHandler(CamWnd::onFrame), NULL, this);
constructGUIComponents();
- GlobalMap().signal_mapValidityChanged().connect(
- sigc::mem_fun(_deferredDraw, &DeferredDraw::onMapValidChanged)
- );
-
// Deactivate all commands, just to make sure
disableDiscreteMoveEvents();
disableFreeMoveEvents();
@@ -335,7 +330,7 @@ SelectionTestPtr CamWnd::createSelectionTestForPoint(const Vector2& point)
float selectEpsilon = registry::getValue<float>(RKEY_SELECT_EPSILON);
// Get the mouse position
- DeviceVector deviceEpsilon(selectEpsilon / getCamera().width, selectEpsilon / getCamera().height);
+ Vector2 deviceEpsilon(selectEpsilon / getCamera().width, selectEpsilon / getCamera().height);
// Copy the current view and constrain it to a small rectangle
render::View scissored(_view);
@@ -775,18 +770,13 @@ void CamWnd::onRender()
draw();
}
-void CamWnd::performDeferredDraw()
-{
- _wxGLWidget->Refresh(false);
-}
-
void CamWnd::draw()
{
if (_drawing) return;
util::ScopedBoolLock lock(_drawing);
- if (GlobalMap().isValid() && GlobalMainFrame().screenUpdatesEnabled())
+ if (GlobalMainFrame().screenUpdatesEnabled())
{
GlobalOpenGL().assertNoErrors();
@@ -929,7 +919,7 @@ void CamWnd::queueDraw()
return;
}
- _deferredDraw.draw();
+ _wxGLWidget->Refresh(false);
}
Vector3 CamWnd::getCameraOrigin() const
@@ -942,6 +932,21 @@ void CamWnd::setCameraOrigin(const Vector3& origin)
_camera.setOrigin(origin);
}
+Vector3 CamWnd::getRightVector() const
+{
+ return _camera.vright;
+}
+
+Vector3 CamWnd::getUpVector() const
+{
+ return _camera.vup;
+}
+
+Vector3 CamWnd::getForwardVector() const
+{
+ return _camera.vpn;
+}
+
Vector3 CamWnd::getCameraAngles() const
{
return _camera.getAngles();
diff --git a/radiant/camera/CamWnd.h b/radiant/camera/CamWnd.h
index fb040b2..79f42d3 100644
--- a/radiant/camera/CamWnd.h
+++ b/radiant/camera/CamWnd.h
@@ -15,7 +15,6 @@
#include <wx/glcanvas.h>
#include <wx/timer.h>
#include "render/View.h"
-#include "map/DeferredDraw.h"
#include "RadiantCameraView.h"
#include "Camera.h"
@@ -77,8 +76,6 @@ private:
wxTimer _timer;
bool _timerLock; // to avoid double-timer-firings
- DeferredDraw _deferredDraw;
-
sigc::connection _glExtensionsInitialisedNotifier;
wxutil::KeyEventFilterPtr _escapeListener;
@@ -111,8 +108,12 @@ public:
Camera& getCamera();
- Vector3 getCameraOrigin() const;
- void setCameraOrigin(const Vector3& origin);
+ Vector3 getCameraOrigin() const override;
+ void setCameraOrigin(const Vector3& origin) override;
+
+ Vector3 getRightVector() const override;
+ Vector3 getUpVector() const override;
+ Vector3 getForwardVector() const override;
Vector3 getCameraAngles() const;
void setCameraAngles(const Vector3& angles);
@@ -174,8 +175,6 @@ private:
void onRender();
void drawTime();
- void performDeferredDraw();
-
CameraMouseToolEvent createMouseEvent(const Vector2& point, const Vector2& delta = Vector2(0, 0));
void onGLResize(wxSizeEvent& ev);
diff --git a/radiant/camera/CameraSettings.cpp b/radiant/camera/CameraSettings.cpp
index 80ef3ae..dbd3a1a 100644
--- a/radiant/camera/CameraSettings.cpp
+++ b/radiant/camera/CameraSettings.cpp
@@ -53,27 +53,25 @@ void CameraSettings::observeKey(const std::string& key)
void CameraSettings::constructPreferencePage()
{
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Camera"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Camera"));
// Add the sliders for the movement and angle speed and connect them to the observer
- page->appendSlider(_("Movement Speed (game units)"), RKEY_MOVEMENT_SPEED, TRUE, 100, 1, MAX_CAMERA_SPEED, 1, 1, 1);
- page->appendSlider(_("Rotation Speed"), RKEY_ROTATION_SPEED, TRUE, 3, 1, 180, 1, 10, 10);
+ page.appendSlider(_("Movement Speed (game units)"), RKEY_MOVEMENT_SPEED, 1, MAX_CAMERA_SPEED, 1, 1);
+ page.appendSlider(_("Rotation Speed"), RKEY_ROTATION_SPEED, 1, 180, 1, 10);
// Add the checkboxes and connect them with the registry key and the according observer
- page->appendCheckBox("", _("Freelook mode can be toggled"), RKEY_TOGGLE_FREE_MOVE);
- page->appendCheckBox("", _("Discrete movement (non-freelook mode)"), RKEY_DISCRETE_MOVEMENT);
- page->appendCheckBox("", _("Enable far-clip plane (hides distant objects)"), RKEY_ENABLE_FARCLIP);
+ page.appendCheckBox(_("Freelook mode can be toggled"), RKEY_TOGGLE_FREE_MOVE);
+ page.appendCheckBox(_("Discrete movement (non-freelook mode)"), RKEY_DISCRETE_MOVEMENT);
+ page.appendCheckBox(_("Enable far-clip plane (hides distant objects)"), RKEY_ENABLE_FARCLIP);
// Add the "inverse mouse vertical axis in free-look mode" preference
- page->appendCheckBox("", _("Invert mouse vertical axis (freelook mode)"), RKEY_INVERT_MOUSE_VERTICAL_AXIS);
+ page.appendCheckBox(_("Invert mouse vertical axis (freelook mode)"), RKEY_INVERT_MOUSE_VERTICAL_AXIS);
// States whether the selection boxes are stippled or not
- page->appendCheckBox("", _("Solid selection boxes"), RKEY_SOLID_SELECTION_BOXES);
+ page.appendCheckBox(_("Solid selection boxes"), RKEY_SOLID_SELECTION_BOXES);
// Whether to show the toolbar (to please the screenspace addicts)
- page->appendCheckBox(
- "", _("Show camera toolbar"), RKEY_SHOW_CAMERA_TOOLBAR
- );
+ page.appendCheckBox(_("Show camera toolbar"), RKEY_SHOW_CAMERA_TOOLBAR);
}
bool CameraSettings::showCameraToolbar() const
diff --git a/radiant/camera/GlobalCamera.cpp b/radiant/camera/GlobalCamera.cpp
index 199e8d5..621f0ea 100644
--- a/radiant/camera/GlobalCamera.cpp
+++ b/radiant/camera/GlobalCamera.cpp
@@ -16,6 +16,7 @@
#include "tools/ShaderClipboardTools.h"
#include "tools/JumpToObjectTool.h"
#include "tools/FreeMoveTool.h"
+#include "tools/PanViewTool.h"
#include "FloatingCamWnd.h"
#include <functional>
@@ -600,6 +601,7 @@ void GlobalCameraManager::initialiseModule(const ApplicationContext& ctx)
IMouseToolGroup& toolGroup = GlobalMouseToolManager().getGroup(IMouseToolGroup::Type::CameraView);
toolGroup.registerMouseTool(std::make_shared<FreeMoveTool>());
+ toolGroup.registerMouseTool(std::make_shared<PanViewTool>());
toolGroup.registerMouseTool(std::make_shared<PickShaderTool>());
toolGroup.registerMouseTool(std::make_shared<PasteShaderProjectedTool>());
toolGroup.registerMouseTool(std::make_shared<PasteShaderNaturalTool>());
diff --git a/radiant/camera/tools/PanViewTool.h b/radiant/camera/tools/PanViewTool.h
new file mode 100644
index 0000000..2987176
--- /dev/null
+++ b/radiant/camera/tools/PanViewTool.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "imousetool.h"
+#include "i18n.h"
+#include "../GlobalCamera.h"
+#include "../CameraSettings.h"
+
+namespace ui
+{
+
+class PanViewTool :
+ public MouseTool
+{
+public:
+ const std::string& getName() override
+ {
+ static std::string name("PanViewTool");
+ return name;
+ }
+
+ const std::string& getDisplayName() override
+ {
+ static std::string displayName(_("Pan Camera View"));
+ return displayName;
+ }
+
+ unsigned int getPointerMode() override
+ {
+ return PointerMode::Capture | PointerMode::Freeze |
+ PointerMode::Hidden | PointerMode::MotionDeltas;
+ }
+
+ Result onMouseDown(Event& ev) override
+ {
+ try
+ {
+ CameraMouseToolEvent& camEvent = dynamic_cast<CameraMouseToolEvent&>(ev);
+
+ // Don't operate when the camera is already in free look mode
+ if (camEvent.getView().freeMoveEnabled())
+ {
+ return Result::Ignored;
+ }
+
+ return Result::Activated;
+ }
+ catch (std::bad_cast&)
+ {
+ }
+
+ return Result::Ignored; // not handled
+ }
+
+ Result onMouseMove(Event& ev) override
+ {
+ try
+ {
+ // We use capture mode, so xy event will contain the delta only
+ CameraMouseToolEvent& camEvent = dynamic_cast<CameraMouseToolEvent&>(ev);
+ ICameraView& view = camEvent.getView();
+
+ const float strafespeed = GlobalCamera().getCameraStrafeSpeed();
+
+ double dx = camEvent.getDeviceDelta().x();
+ double dy = camEvent.getDeviceDelta().y();
+
+ Vector3 delta(0, 0, 0);
+
+ delta += view.getRightVector() * strafespeed * dx;
+ delta += view.getUpVector() * strafespeed * dy * (-1); // invert y direction
+
+ view.setCameraOrigin(view.getCameraOrigin() + delta);
+
+ return Result::Continued;
+ }
+ catch (std::bad_cast&)
+ {
+ }
+
+ return Result::Ignored;
+ }
+
+ Result onMouseUp(Event& ev) override
+ {
+ return Result::Finished;
+ }
+};
+
+}
diff --git a/radiant/clipper/Clipper.cpp b/radiant/clipper/Clipper.cpp
index f7b4c02..4ce2578 100644
--- a/radiant/clipper/Clipper.cpp
+++ b/radiant/clipper/Clipper.cpp
@@ -38,10 +38,10 @@ void Clipper::keyChanged()
}
void Clipper::constructPreferences() {
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Clipper"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Clipper"));
- page->appendCheckBox("", _("Clipper tool uses caulk texture"), RKEY_CLIPPER_USE_CAULK);
- page->appendEntry(_("Caulk shader name"), RKEY_CLIPPER_CAULK_SHADER);
+ page.appendCheckBox(_("Clipper tool uses caulk texture"), RKEY_CLIPPER_USE_CAULK);
+ page.appendEntry(_("Caulk shader name"), RKEY_CLIPPER_CAULK_SHADER);
}
EViewType Clipper::getViewType() const {
diff --git a/radiant/darkradiant.rc b/radiant/darkradiant.rc
index f773827..c262e14 100644
--- a/radiant/darkradiant.rc
+++ b/radiant/darkradiant.rc
@@ -1,4 +1,5 @@
#include "../w32deps/wxWidgets/include/wx/msw/wx.rc"
+#include "../include/version.h"
//Microsoft Developer Studio generated resource script.
//
@@ -72,3 +73,25 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2.0.0
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "ProductName", RADIANT_APPNAME
+ VALUE "ProductVersion", RADIANT_VERSION RADIANT_BLANK RADIANT_PLATFORM "\0"
+ VALUE "LegalCopyright", "www.thedarkmod.com" "\0"
+ VALUE "FileDescription", "Level Editor for The Dark Mod" "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/radiant/layers/LayerInfoFileModule.cpp b/radiant/layers/LayerInfoFileModule.cpp
new file mode 100644
index 0000000..2aac129
--- /dev/null
+++ b/radiant/layers/LayerInfoFileModule.cpp
@@ -0,0 +1,282 @@
+#include "LayerInfoFileModule.h"
+
+#include "ilayer.h"
+#include "ientity.h"
+#include "itextstream.h"
+#include "scenelib.h"
+#include "scene/LayerValidityCheckWalker.h"
+#include "string/convert.h"
+#include "debugging/ScenegraphUtils.h"
+#include "parser/DefTokeniser.h"
+
+namespace scene
+{
+
+namespace
+{
+ const char* const NODE_TO_LAYER_MAPPING = "NodeToLayerMapping";
+ const char* const LAYER = "Layer";
+ const char* const LAYERS = "Layers";
+ const char* const NODE = "Node";
+}
+
+LayerInfoFileModule::LayerInfoFileModule() :
+ _layerInfoCount(0)
+{
+ _standardLayerList.insert(0);
+}
+
+std::string LayerInfoFileModule::getName()
+{
+ return "Layer Mapping";
+}
+
+void LayerInfoFileModule::onInfoFileSaveStart()
+{
+ _layerInfoCount = 0;
+ _output.str(std::string());
+ _output.clear();
+}
+
+void LayerInfoFileModule::onSavePrimitive(const INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
+{
+ saveNode(node);
+}
+
+void LayerInfoFileModule::onSaveEntity(const INodePtr& node, std::size_t entityNum)
+{
+ saveNode(node);
+}
+
+void LayerInfoFileModule::saveNode(const INodePtr& node)
+{
+ // Don't export the layer settings for models and particles, as they are not there
+ // at map load/parse time - these shouldn't even be passed in here
+ assert(Node_isEntity(node) || Node_isPrimitive(node));
+
+ // Open a Node block
+ _output << "\t\t" << NODE << " { ";
+
+ scene::LayerList layers = node->getLayers();
+
+ // Write a space-separated list of node IDs
+ for (const scene::LayerList::value_type& i : layers)
+ {
+ _output << i << " ";
+ }
+
+ // Close the Node block
+ _output << "}";
+
+ // Write additional node info, for easier debugging of layer issues
+ _output << " // " << getNodeInfo(node);
+
+ _output << std::endl;
+
+ _layerInfoCount++;
+}
+
+void LayerInfoFileModule::writeBlocks(std::ostream& stream)
+{
+ // Write the layer names block
+ writeLayerNames(stream);
+
+ // Write the NodeToLayerMapping block
+ stream << "\t" << NODE_TO_LAYER_MAPPING << std::endl;
+ stream << "\t{" << std::endl;
+
+ // Write the output buffer to the stream
+ stream << _output.rdbuf();
+
+ // Closing braces of NodeToLayerMapping block
+ stream << "\t}" << std::endl;
+
+ rMessage() << _layerInfoCount << " node-to-layer mappings written." << std::endl;
+}
+
+void LayerInfoFileModule::onInfoFileSaveFinished()
+{
+ _layerInfoCount = 0;
+ _output.str(std::string());
+ _output.clear();
+}
+
+void LayerInfoFileModule::onInfoFileLoadStart()
+{
+ _layerNames.clear();
+ _layerMappings.clear();
+}
+
+bool LayerInfoFileModule::canParseBlock(const std::string& blockName)
+{
+ return blockName == LAYERS || blockName == NODE_TO_LAYER_MAPPING;
+}
+
+void LayerInfoFileModule::parseBlock(const std::string& blockName, parser::DefTokeniser& tok)
+{
+ assert(canParseBlock(blockName));
+
+ if (blockName == LAYERS)
+ {
+ parseLayerNames(tok);
+ }
+ else if (blockName == NODE_TO_LAYER_MAPPING)
+ {
+ parseNodeToLayerMapping(tok);
+ }
+}
+
+void LayerInfoFileModule::parseLayerNames(parser::DefTokeniser& tok)
+{
+ // The opening brace
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == LAYER)
+ {
+ // Get the ID
+ std::string layerIDStr = tok.nextToken();
+ int layerID = string::convert<int>(layerIDStr);
+
+ tok.assertNextToken("{");
+
+ // Assemble the name
+ std::string name;
+
+ token = tok.nextToken();
+
+ while (token != "}")
+ {
+ name += token;
+ token = tok.nextToken();
+ }
+
+ rMessage() << "[InfoFile]: Parsed layer #" << layerID << " with name " << name << std::endl;
+
+ _layerNames.insert(LayerNameMap::value_type(layerID, name));
+
+ continue;
+ }
+
+ if (token == "}")
+ {
+ break;
+ }
+ }
+}
+
+void LayerInfoFileModule::parseNodeToLayerMapping(parser::DefTokeniser& tok)
+{
+ // The opening brace
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == NODE)
+ {
+ tok.assertNextToken("{");
+
+ // Create a new LayerList
+ _layerMappings.push_back(scene::LayerList());
+
+ while (tok.hasMoreTokens())
+ {
+ std::string nodeToken = tok.nextToken();
+
+ if (nodeToken == "}")
+ {
+ break;
+ }
+
+ // Add the ID to the list
+ _layerMappings.back().insert(string::convert<int>(nodeToken));
+ }
+ }
+
+ if (token == "}")
+ {
+ break;
+ }
+ }
+}
+
+void LayerInfoFileModule::applyInfoToScene(const IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap)
+{
+ // Create the layers according to the data found in the map information file
+ for (const LayerNameMap::value_type& i : _layerNames)
+ {
+ // Create the named layer with the saved ID
+ GlobalLayerSystem().createLayer(i.second, i.first);
+ }
+
+ // Set the layer mapping iterator to the beginning
+ LayerLists::const_iterator mapping = _layerMappings.begin();
+
+ // Assign the layers
+ root->foreachNode([&](const INodePtr& node)
+ {
+ // To prevent all the support node types from getting layers assigned
+ // filter them out, only Entities and Primitives get mapped in the info file
+ if (Node_isEntity(node) || Node_isPrimitive(node))
+ {
+ // Check if the node index is out of bounds
+ if (mapping == _layerMappings.end())
+ {
+ node->assignToLayers(_standardLayerList);
+ return true;
+ }
+
+ // Retrieve the next set of layer mappings and assign them
+ node->assignToLayers(*(mapping++));
+ return true;
+ }
+
+ // All other node types inherit the layers from their parent node
+ // Model / particle / target line
+ scene::INodePtr parent = node->getParent();
+
+ if (parent)
+ {
+ node->assignToLayers(parent->getLayers());
+ }
+
+ return true;
+ });
+
+ rMessage() << "Sanity-checking the layer assignments...";
+
+ // Sanity-check the layer mapping, it's possible that some .darkradiant
+ // files are mapping nodes to non-existent layer IDs
+ LayerValidityCheckWalker checker;
+ root->traverseChildren(checker);
+
+ rMessage() << "done, had to fix " << checker.getNumFixed() << " assignments." << std::endl;
+}
+
+void LayerInfoFileModule::onInfoFileLoadFinished()
+{
+ _layerNames.clear();
+ _layerMappings.clear();
+}
+
+void LayerInfoFileModule::writeLayerNames(std::ostream& stream)
+{
+ // Open a "Layers" block
+ stream << "\t" << LAYERS << std::endl;
+ stream << "\t{" << std::endl;
+
+ // Visit all layers and write them to the stream
+ GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName)
+ {
+ stream << "\t\t" << LAYER << " " << layerId << " { " << layerName << " }" << std::endl;
+ });
+
+ stream << "\t}" << std::endl;
+}
+
+}
diff --git a/radiant/layers/LayerInfoFileModule.h b/radiant/layers/LayerInfoFileModule.h
new file mode 100644
index 0000000..c0f73c0
--- /dev/null
+++ b/radiant/layers/LayerInfoFileModule.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "imapinfofile.h"
+#include <sstream>
+
+namespace scene
+{
+
+class LayerInfoFileModule :
+ public map::IMapInfoFileModule
+{
+private:
+ // Number of node-to-layer mappings written
+ std::size_t _layerInfoCount;
+
+ // Buffer to hold our output
+ std::stringstream _output;
+
+ // The list of layernames
+ typedef std::map<int, std::string> LayerNameMap;
+ LayerNameMap _layerNames;
+
+ typedef std::vector<scene::LayerList> LayerLists;
+ LayerLists _layerMappings;
+
+ // The standard list (node is part of layer 0)
+ scene::LayerList _standardLayerList;
+
+public:
+ LayerInfoFileModule();
+
+ std::string getName() override;
+
+ void onInfoFileSaveStart() override;
+ void onSavePrimitive(const INodePtr& node, std::size_t entityNum, std::size_t primitiveNum) override;
+ void onSaveEntity(const INodePtr& node, std::size_t entityNum) override;
+ void writeBlocks(std::ostream& stream) override;
+ void onInfoFileSaveFinished() override;
+
+ void onInfoFileLoadStart() override;
+ bool canParseBlock(const std::string& blockName) override;
+ void parseBlock(const std::string& blockName, parser::DefTokeniser& tok) override;
+ void applyInfoToScene(const IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap) override;
+ void onInfoFileLoadFinished() override;
+
+private:
+ void saveNode(const INodePtr& node);
+ void writeLayerNames(std::ostream& stream);
+
+ void parseLayerNames(parser::DefTokeniser& tok);
+ void parseNodeToLayerMapping(parser::DefTokeniser& tok);
+};
+
+}
diff --git a/radiant/layers/LayerSystem.cpp b/radiant/layers/LayerSystem.cpp
index e04bd1b..97dc6cf 100644
--- a/radiant/layers/LayerSystem.cpp
+++ b/radiant/layers/LayerSystem.cpp
@@ -6,6 +6,7 @@
#include "iuimanager.h"
#include "itextstream.h"
#include "imainframe.h"
+#include "imapinfofile.h"
#include "icommandsystem.h"
#include "scene/Node.h"
#include "scenelib.h"
@@ -15,6 +16,7 @@
#include "MoveToLayerWalker.h"
#include "RemoveFromLayerWalker.h"
#include "SetLayerSelectedWalker.h"
+#include "LayerInfoFileModule.h"
#include "wxutil/dialog/Dialog.h"
#include "wxutil/dialog/MessageBox.h"
@@ -466,6 +468,7 @@ const StringSet& LayerSystem::getDependencies() const
_dependencies.insert(MODULE_COMMANDSYSTEM);
_dependencies.insert(MODULE_UIMANAGER);
_dependencies.insert(MODULE_ORTHOCONTEXTMENU);
+ _dependencies.insert(MODULE_MAPINFOFILEMANAGER);
}
return _dependencies;
@@ -473,7 +476,7 @@ const StringSet& LayerSystem::getDependencies() const
void LayerSystem::initialiseModule(const ApplicationContext& ctx)
{
- rMessage() << "LayerSystem::initialiseModule called.\n";
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
// Create the "master" layer with ID DEFAULT_LAYER
createLayer(_(DEFAULT_LAYER_NAME));
@@ -494,6 +497,9 @@ void LayerSystem::initialiseModule(const ApplicationContext& ctx)
GlobalCommandSystem().addCommand("ToggleLayerControlDialog", ui::LayerControlDialog::toggle);
GlobalEventManager().addCommand("ToggleLayerControlDialog", "ToggleLayerControlDialog");
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &LayerSystem::onMapEvent)
+ );
// Create a new menu item connected to the CreateNewLayer command
wxutil::CommandMenuItemPtr menuItem(new wxutil::CommandMenuItem(
@@ -516,6 +522,10 @@ void LayerSystem::initialiseModule(const ApplicationContext& ctx)
GlobalOrthoContextMenu().addItem(addMenu, ui::IOrthoContextMenu::SECTION_LAYER);
GlobalOrthoContextMenu().addItem(moveMenu, ui::IOrthoContextMenu::SECTION_LAYER);
GlobalOrthoContextMenu().addItem(removeMenu, ui::IOrthoContextMenu::SECTION_LAYER);
+
+ GlobalMapInfoFileManager().registerInfoFileModule(
+ std::make_shared<LayerInfoFileModule>()
+ );
}
void LayerSystem::createLayerCmd(const cmd::ArgumentList& args)
@@ -570,6 +580,15 @@ void LayerSystem::createLayerCmd(const cmd::ArgumentList& args)
}
}
+void LayerSystem::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloaded || ev == IMap::MapLoading)
+ {
+ // Purge layer info before map is loading or after it has been unloaded
+ reset();
+ }
+}
+
// Define the static LayerSystem module
module::StaticModule<LayerSystem> layerSystemModule;
diff --git a/radiant/layers/LayerSystem.h b/radiant/layers/LayerSystem.h
index 667fb3e..e50fc8a 100644
--- a/radiant/layers/LayerSystem.h
+++ b/radiant/layers/LayerSystem.h
@@ -3,6 +3,7 @@
#include <vector>
#include <map>
#include "ilayer.h"
+#include "imap.h"
#include "LayerCommandTarget.h"
namespace scene {
@@ -129,6 +130,8 @@ public:
void createLayerCmd(const cmd::ArgumentList& args);
private:
+ void onMapEvent(IMap::MapEvent ev);
+
// Internal event, updates the scenegraph
void onLayerVisibilityChanged();
diff --git a/radiant/layers/SetLayerSelectedWalker.h b/radiant/layers/SetLayerSelectedWalker.h
index b45520e..f63324e 100644
--- a/radiant/layers/SetLayerSelectedWalker.h
+++ b/radiant/layers/SetLayerSelectedWalker.h
@@ -2,6 +2,7 @@
#include "ientity.h"
#include "ilayer.h"
+#include "entitylib.h"
namespace scene
{
@@ -26,9 +27,7 @@ public:
return false; // skip hidden nodes
}
- Entity* entity = Node_getEntity(node);
-
- if (entity != NULL && entity->getKeyValue("classname") == "worldspawn")
+ if (Node_isWorldspawn(node))
{
// Skip the worldspawn
return true;
diff --git a/radiant/map/AasFileManager.cpp b/radiant/map/AasFileManager.cpp
new file mode 100644
index 0000000..4d3ea6f
--- /dev/null
+++ b/radiant/map/AasFileManager.cpp
@@ -0,0 +1,170 @@
+#include "AasFileManager.h"
+
+#include "itextstream.h"
+
+#include "iarchive.h"
+#include "ieclass.h"
+#include "ifilesystem.h"
+#include "eclass.h"
+
+#include "modulesystem/StaticModule.h"
+#include "ui/aas/AasControlDialog.h"
+
+namespace map
+{
+
+namespace
+{
+ const char* const AAS_TYPES_ENTITYDEF = "aas_types";
+}
+
+AasFileManager::AasFileManager() :
+ _typesLoaded(false)
+{}
+
+void AasFileManager::registerLoader(const IAasFileLoaderPtr& loader)
+{
+ _loaders.insert(loader);
+}
+
+void AasFileManager::unregisterLoader(const IAasFileLoaderPtr& loader)
+{
+ _loaders.erase(loader);
+}
+
+IAasFileLoaderPtr AasFileManager::getLoaderForStream(std::istream& stream)
+{
+ IAasFileLoaderPtr loader;
+
+ for (const IAasFileLoaderPtr& candidate : _loaders)
+ {
+ // Rewind the stream before passing it to the format for testing
+ stream.seekg(0, std::ios_base::beg);
+
+ if (candidate->canLoad(stream))
+ {
+ loader = candidate;
+ break;
+ }
+ }
+
+ // Rewind the stream when we're done
+ stream.seekg(0, std::ios_base::beg);
+
+ return loader;
+}
+
+void AasFileManager::ensureAasTypesLoaded()
+{
+ if (_typesLoaded) return;
+
+ _typesLoaded = true;
+ _typeList.clear();
+
+ IEntityClassPtr aasTypesClass = GlobalEntityClassManager().findClass(AAS_TYPES_ENTITYDEF);
+
+ if (aasTypesClass)
+ {
+ eclass::AttributeList list = eclass::getSpawnargsWithPrefix(*aasTypesClass, "type");
+
+ for (const EntityClassAttribute& attr : list)
+ {
+ AasType type;
+ type.entityDefName = attr.getValue();
+
+ IEntityClassPtr aasType = GlobalEntityClassManager().findClass(type.entityDefName);
+
+ if (!aasType)
+ {
+ rWarning() << "Could not find entityDef for AAS type " << type.entityDefName <<
+ " mentioned in " << AAS_TYPES_ENTITYDEF << " entityDef." << std::endl;
+ continue;
+ }
+
+ type.fileExtension = aasType->getAttribute("fileExtension").getValue();
+ _typeList.push_back(type);
+ }
+ }
+}
+
+AasTypeList AasFileManager::getAasTypes()
+{
+ ensureAasTypesLoaded();
+
+ return _typeList;
+}
+
+AasType AasFileManager::getAasTypeByName(const std::string& typeName)
+{
+ ensureAasTypesLoaded();
+
+ for (AasType& type : _typeList)
+ {
+ if (type.entityDefName == typeName)
+ {
+ return type;
+ }
+ }
+
+ throw std::runtime_error("Could not find AAS type " + typeName);
+}
+
+std::list<AasFileInfo> AasFileManager::getAasFilesForMap(const std::string& mapPath)
+{
+ std::list<AasFileInfo> list;
+
+ AasTypeList types = getAasTypes();
+
+ for (const AasType& type : types)
+ {
+ std::string path = mapPath;
+
+ // Cut off the extension
+ path = path.substr(0, path.rfind('.'));
+ path += "." + type.fileExtension;
+
+ ArchiveTextFilePtr file = GlobalFileSystem().openTextFileInAbsolutePath(path);
+
+ if (file)
+ {
+ // Add this file to the list
+ list.push_back(AasFileInfo());
+ list.back().absolutePath = path;
+ list.back().type = type;
+ }
+ }
+
+ return list;
+}
+
+const std::string& AasFileManager::getName() const
+{
+ static std::string _name(MODULE_AASFILEMANAGER);
+ return _name;
+}
+
+const StringSet& AasFileManager::getDependencies() const
+{
+ static StringSet _dependencies;
+
+ if (_dependencies.empty())
+ {
+ _dependencies.insert(MODULE_VIRTUALFILESYSTEM);
+ _dependencies.insert(MODULE_ECLASSMANAGER);
+ }
+
+ return _dependencies;
+}
+
+void AasFileManager::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
+
+ // Initialise the UI
+ ui::AasControlDialog::Init();
+}
+
+// Define the static AasFileManager module
+module::StaticModule<AasFileManager> aasFileManagerModule;
+
+}
diff --git a/radiant/map/AasFileManager.h b/radiant/map/AasFileManager.h
new file mode 100644
index 0000000..14e3692
--- /dev/null
+++ b/radiant/map/AasFileManager.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "iaasfile.h"
+#include <set>
+
+namespace map
+{
+
+class AasFileManager :
+ public IAasFileManager
+{
+private:
+ // A mapping between extensions and format modules
+ // Multiple modules can register themselves for a single extension
+ typedef std::set<IAasFileLoaderPtr> Loaders;
+ Loaders _loaders;
+
+ AasTypeList _typeList;
+ bool _typesLoaded;
+
+public:
+ AasFileManager();
+
+ // IAasFileManager implementation
+ void registerLoader(const IAasFileLoaderPtr& loader) override;
+ void unregisterLoader(const IAasFileLoaderPtr& loader) override;
+ IAasFileLoaderPtr getLoaderForStream(std::istream& stream) override;
+ AasTypeList getAasTypes() override;
+ AasType getAasTypeByName(const std::string& typeName) override;
+ std::list<AasFileInfo> getAasFilesForMap(const std::string& mapPath) override;
+
+ // RegisterableModule implementation
+ const std::string& getName() const override;
+ const StringSet& getDependencies() const override;
+ void initialiseModule(const ApplicationContext& ctx) override;
+
+private:
+ void ensureAasTypesLoaded();
+};
+
+} // namespace
diff --git a/radiant/map/AutoSaver.cpp b/radiant/map/AutoSaver.cpp
index 8421850..4d609f7 100644
--- a/radiant/map/AutoSaver.cpp
+++ b/radiant/map/AutoSaver.cpp
@@ -5,8 +5,8 @@
#include "mapfile.h"
#include "itextstream.h"
#include "iscenegraph.h"
-#include "imainframe.h"
#include "iradiant.h"
+#include "imainframe.h"
#include "ipreferencesystem.h"
#include "registry/registry.h"
@@ -21,6 +21,7 @@
#include "string/string.h"
#include "map/Map.h"
#include "modulesystem/ApplicationContextImpl.h"
+#include "modulesystem/StaticModule.h"
#include <wx/frame.h>
@@ -28,11 +29,12 @@
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/exception.hpp>
-namespace map {
-
-namespace {
+namespace map
+{
- /* Registry key names */
+namespace
+{
+ // Registry key names
const char* RKEY_AUTOSAVE_ENABLED = "user/ui/map/autoSaveEnabled";
const char* RKEY_AUTOSAVE_INTERVAL = "user/ui/map/autoSaveInterval";
const char* RKEY_AUTOSAVE_SNAPSHOTS_ENABLED = "user/ui/map/autoSaveSnapshots";
@@ -44,35 +46,16 @@ namespace {
typedef boost::filesystem::path Path;
}
-
AutoMapSaver::AutoMapSaver() :
- _enabled(registry::getValue<bool>(RKEY_AUTOSAVE_ENABLED)),
- _snapshotsEnabled(registry::getValue<bool>(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED)),
- _interval(registry::getValue<int>(RKEY_AUTOSAVE_INTERVAL) * 60),
- _timer(this),
+ _enabled(false),
+ _snapshotsEnabled(false),
+ _interval(5*60),
_changes(0)
-{
- Connect(wxEVT_TIMER, wxTimerEventHandler(AutoMapSaver::onIntervalReached), NULL, this);
-
- GlobalRegistry().signalForKey(RKEY_AUTOSAVE_INTERVAL).connect(
- sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
- );
- GlobalRegistry().signalForKey(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED).connect(
- sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
- );
- GlobalRegistry().signalForKey(RKEY_AUTOSAVE_ENABLED).connect(
- sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
- );
-
- // Register this instance with GlobalRadiant() at once
- GlobalRadiant().signal_radiantShutdown().connect(
- sigc::mem_fun(*this, &AutoMapSaver::onRadiantShutdown)
- );
-}
+{}
AutoMapSaver::~AutoMapSaver()
{
- stopTimer();
+ assert(!_timer);
}
void AutoMapSaver::registryKeyChanged()
@@ -91,17 +74,6 @@ void AutoMapSaver::registryKeyChanged()
}
}
-void AutoMapSaver::init()
-{
- constructPreferences();
-}
-
-void AutoMapSaver::onRadiantShutdown()
-{
- _enabled = false;
- stopTimer();
-}
-
void AutoMapSaver::clearChanges()
{
_changes = 0;
@@ -109,12 +81,18 @@ void AutoMapSaver::clearChanges()
void AutoMapSaver::startTimer()
{
- _timer.Start(_interval * 1000);
+ assert(_timer);
+ if (!_timer) return;
+
+ _timer->Start(_interval * 1000);
}
void AutoMapSaver::stopTimer()
{
- _timer.Stop();
+ assert(_timer);
+ if (!_timer) return;
+
+ _timer->Stop();
}
void AutoMapSaver::saveSnapshot()
@@ -168,7 +146,7 @@ void AutoMapSaver::saveSnapshot()
if (os::fileOrDirExists(filename))
{
// Add to the folder size
- folderSize += file_size(filename.c_str());
+ folderSize += os::getFileSize(filename);
}
else
{
@@ -199,8 +177,7 @@ void AutoMapSaver::saveSnapshot()
void AutoMapSaver::checkSave()
{
- // Check if we have a proper map
- if (!GlobalMap().isValid() || !GlobalMainFrame().screenUpdatesEnabled())
+ if (!GlobalMainFrame().screenUpdatesEnabled())
{
return;
}
@@ -296,15 +273,15 @@ void AutoMapSaver::checkSave()
void AutoMapSaver::constructPreferences()
{
// Add a page to the given group
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Autosave"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Autosave"));
// Add the checkboxes and connect them with the registry key and the according observer
- page->appendCheckBox("", _("Enable Autosave"), RKEY_AUTOSAVE_ENABLED);
- page->appendSlider(_("Autosave Interval (in minutes)"), RKEY_AUTOSAVE_INTERVAL, TRUE, 5, 1, 61, 1, 1, 1);
+ page.appendCheckBox(_("Enable Autosave"), RKEY_AUTOSAVE_ENABLED);
+ page.appendSlider(_("Autosave Interval (in minutes)"), RKEY_AUTOSAVE_INTERVAL, 1, 61, 1, 1);
- page->appendCheckBox("", _("Save Snapshots"), RKEY_AUTOSAVE_SNAPSHOTS_ENABLED);
- page->appendEntry(_("Snapshot folder (relative to map folder)"), RKEY_AUTOSAVE_SNAPSHOTS_FOLDER);
- page->appendEntry(_("Max Snapshot Folder size (MB)"), RKEY_AUTOSAVE_MAX_SNAPSHOT_FOLDER_SIZE);
+ page.appendCheckBox(_("Save Snapshots"), RKEY_AUTOSAVE_SNAPSHOTS_ENABLED);
+ page.appendEntry(_("Snapshot folder (relative to map folder)"), RKEY_AUTOSAVE_SNAPSHOTS_FOLDER);
+ page.appendEntry(_("Max Snapshot Folder size (MB)"), RKEY_AUTOSAVE_MAX_SNAPSHOT_FOLDER_SIZE);
}
void AutoMapSaver::onIntervalReached(wxTimerEvent& ev)
@@ -312,10 +289,94 @@ void AutoMapSaver::onIntervalReached(wxTimerEvent& ev)
checkSave();
}
+void AutoMapSaver::onMapEvent(IMap::MapEvent ev)
+{
+ // We reset our change count regardless of whether a map
+ // is loaded or unloaded
+ switch (ev)
+ {
+ case IMap::MapLoading:
+ case IMap::MapLoaded:
+ case IMap::MapUnloading:
+ case IMap::MapUnloaded:
+ clearChanges();
+ break;
+ };
+}
+
+const std::string& AutoMapSaver::getName() const
+{
+ static std::string _name("AutomaticMapSaver");
+ return _name;
+}
+
+const StringSet& AutoMapSaver::getDependencies() const
+{
+ static StringSet _dependencies;
+
+ if (_dependencies.empty())
+ {
+ _dependencies.insert(MODULE_MAP);
+ _dependencies.insert(MODULE_PREFERENCESYSTEM);
+ _dependencies.insert(MODULE_XMLREGISTRY);
+ _dependencies.insert(MODULE_MAINFRAME);
+ _dependencies.insert(MODULE_RADIANT);
+ }
+
+ return _dependencies;
+}
+
+void AutoMapSaver::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
+
+ _timer.reset(new wxTimer(this));
+
+ constructPreferences();
+
+ Connect(wxEVT_TIMER, wxTimerEventHandler(AutoMapSaver::onIntervalReached), NULL, this);
+
+ _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_INTERVAL).connect(
+ sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
+ ));
+ _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_SNAPSHOTS_ENABLED).connect(
+ sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
+ ));
+ _signalConnections.push_back(GlobalRegistry().signalForKey(RKEY_AUTOSAVE_ENABLED).connect(
+ sigc::mem_fun(this, &AutoMapSaver::registryKeyChanged)
+ ));
+
+ // Get notified when the map is loaded afresh
+ _signalConnections.push_back(GlobalMap().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &AutoMapSaver::onMapEvent)
+ ));
+
+ // Refresh all values from the registry right now (this might also start the timer)
+ registryKeyChanged();
+}
+
+void AutoMapSaver::shutdownModule()
+{
+ // Unsubscribe from all connections
+ for (sigc::connection& connection : _signalConnections)
+ {
+ connection.disconnect();
+ }
+
+ _signalConnections.clear();
+
+ _enabled = false;
+ stopTimer();
+
+ // Destroy the timer
+ _timer.reset();
+}
+
+module::StaticModule<AutoMapSaver> staticAutoSaverModule;
+
AutoMapSaver& AutoSaver()
{
- static AutoMapSaver _autoSaver;
- return _autoSaver;
+ return *staticAutoSaverModule.getModule();
}
} // namespace map
diff --git a/radiant/map/AutoSaver.h b/radiant/map/AutoSaver.h
index fac5da5..714bddb 100644
--- a/radiant/map/AutoSaver.h
+++ b/radiant/map/AutoSaver.h
@@ -1,8 +1,13 @@
#pragma once
#include "iregistry.h"
+#include "imodule.h"
+#include "imap.h"
+#include <vector>
+#include <sigc++/connection.h>
#include <wx/timer.h>
+#include <wx/sharedptr.h>
/* greebo: The AutoMapSaver class lets itself being called in distinct intervals
* and saves the map files either to snapshots or to a single yyyy.autosave.map file.
@@ -12,8 +17,8 @@ namespace map
{
class AutoMapSaver :
- public sigc::trackable,
- public wxEvtHandler
+ public wxEvtHandler,
+ public RegisterableModule
{
// TRUE, if autosaving is enabled
bool _enabled;
@@ -25,16 +30,21 @@ class AutoMapSaver :
unsigned long _interval;
// The timer object that triggers the callback
- wxTimer _timer;
+ wxSharedPtr<wxTimer> _timer;
std::size_t _changes;
+ std::vector<sigc::connection> _signalConnections;
+
public:
// Constructor
AutoMapSaver();
- // Initialises the preferences and the registrykeyobserver
- void init();
+ // RegisterableModule implementation
+ const std::string& getName() const override;
+ const StringSet& getDependencies() const override;
+ void initialiseModule(const ApplicationContext& ctx) override;
+ void shutdownModule() override;
~AutoMapSaver();
@@ -45,13 +55,13 @@ public:
// Clears the _changes member variable that indicates how many changes have been made
void clearChanges();
- void registryKeyChanged();
-
+private:
// Adds the elements to the according preference page
void constructPreferences();
-private:
- void onRadiantShutdown();
+ void registryKeyChanged();
+
+ void onMapEvent(IMap::MapEvent ev);
// This performs is called to check if the map is valid/changed/should be saved
// and calls the save routines accordingly.
diff --git a/radiant/map/CounterManager.cpp b/radiant/map/CounterManager.cpp
index ee800f4..f373ee9 100644
--- a/radiant/map/CounterManager.cpp
+++ b/radiant/map/CounterManager.cpp
@@ -2,6 +2,7 @@
#include "i18n.h"
#include "iuimanager.h"
+#include "selectionlib.h"
#include "string/string.h"
#include "modulesystem/StaticModule.h"
@@ -46,6 +47,7 @@ const StringSet& CounterManager::getDependencies() const
if (_dependencies.empty())
{
_dependencies.insert(MODULE_UIMANAGER);
+ _dependencies.insert(MODULE_SELECTIONSYSTEM);
}
return _dependencies;
@@ -57,17 +59,32 @@ void CounterManager::initialiseModule(const ApplicationContext& ctx)
GlobalUIManager().getStatusBarManager().addTextElement(
"MapCounters",
"", // no icon
- IStatusBarManager::POS_BRUSHCOUNT
+ IStatusBarManager::POS_BRUSHCOUNT,
+ _("Number of brushes/patches/entities in this map\n(Number of selected items shown in parentheses)")
);
+
+ _selectionChangedConn = GlobalSelectionSystem().signal_selectionChanged().connect(
+ [this] (const ISelectable&) { requestIdleCallback(); }
+ );
+}
+
+void CounterManager::shutdownModule()
+{
+ _selectionChangedConn.disconnect();
}
void CounterManager::onIdle()
{
+ const SelectionInfo& info = GlobalSelectionSystem().getSelectionInfo();
+
std::string text =
- (boost::format(_("Brushes: %lu Patches: %lu Entities: %lu")) %
+ (boost::format(_("Brushes: %lu (%lu) Patches: %lu (%lu) Entities: %lu (%lu)")) %
_counters[counterBrushes]->get() %
+ info.brushCount %
_counters[counterPatches]->get() %
- _counters[counterEntities]->get()).str();
+ info.patchCount %
+ _counters[counterEntities]->get() %
+ info.entityCount).str();
GlobalUIManager().getStatusBarManager().setText("MapCounters", text);
}
diff --git a/radiant/map/CounterManager.h b/radiant/map/CounterManager.h
index 95d0677..9d3a4da 100644
--- a/radiant/map/CounterManager.h
+++ b/radiant/map/CounterManager.h
@@ -4,6 +4,7 @@
#include "iuimanager.h"
#include "wxutil/event/SingleIdleCallback.h"
+#include <sigc++/connection.h>
#include <map>
#include <memory>
@@ -52,22 +53,25 @@ class CounterManager :
typedef std::map<CounterType, CounterPtr> CounterMap;
CounterMap _counters;
+ sigc::connection _selectionChangedConn;
+
public:
CounterManager();
virtual ~CounterManager() {}
- ICounter& getCounter(CounterType counter);
+ ICounter& getCounter(CounterType counter) override;
// ICounter::Observer implementation
- void countChanged();
+ void countChanged() override;
- const std::string& getName() const;
- const StringSet& getDependencies() const;
- void initialiseModule(const ApplicationContext& ctx);
+ const std::string& getName() const override;
+ const StringSet& getDependencies() const override;
+ void initialiseModule(const ApplicationContext& ctx) override;
+ void shutdownModule() override;
protected:
- void onIdle();
+ void onIdle() override;
};
} // namespace map
diff --git a/radiant/map/DeferredDraw.h b/radiant/map/DeferredDraw.h
deleted file mode 100644
index 7154abf..0000000
--- a/radiant/map/DeferredDraw.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#pragma once
-
-#include <functional>
-#include "map/Map.h"
-#include <sigc++/trackable.h>
-
-class DeferredDraw :
- public sigc::trackable
-{
-public:
- typedef std::function<void()> DrawCallback;
-
-private:
- DrawCallback _draw;
- bool _defer;
- bool _deferred;
-public:
- DeferredDraw(const DrawCallback& draw) :
- _draw(draw),
- _defer(false),
- _deferred(false)
- {}
-
- void defer() {
- _defer = true;
- }
-
- void draw()
- {
- if (_defer)
- {
- _deferred = true;
- }
- else
- {
- _draw();
- }
- }
-
- void flush()
- {
- if (_defer && _deferred && _draw)
- {
- _draw();
- }
-
- _deferred = false;
- _defer = false;
- }
-
- // Callback target
- void onMapValidChanged()
- {
- if (GlobalMap().isValid())
- {
- flush();
- }
- else
- {
- defer();
- }
- }
-};
diff --git a/radiant/map/InfoFile.cpp b/radiant/map/InfoFile.cpp
deleted file mode 100644
index 0fd76c4..0000000
--- a/radiant/map/InfoFile.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-#include "InfoFile.h"
-
-#include <limits>
-#include "itextstream.h"
-#include "string/convert.h"
-
-#include "i18n.h"
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/replace.hpp>
-#include <boost/lexical_cast.hpp>
-
-namespace map
-{
-
-const char* const InfoFile::HEADER_SEQUENCE = "DarkRadiant Map Information File Version";
-const char* const InfoFile::NODE_TO_LAYER_MAPPING = "NodeToLayerMapping";
-const char* const InfoFile::LAYER = "Layer";
-const char* const InfoFile::LAYERS = "Layers";
-const char* const InfoFile::NODE = "Node";
-const char* const InfoFile::SELECTION_SETS = "SelectionSets";
-const char* const InfoFile::SELECTION_SET = "SelectionSet";
-
-std::size_t InfoFile::EMPTY_PRIMITVE_NUM = std::numeric_limits<std::size_t>::max();
-
-// Pass the input stream to the constructor
-InfoFile::InfoFile(std::istream& infoStream) :
- _tok(infoStream),
- _isValid(true)
-{
- _standardLayerList.insert(0);
-}
-
-const InfoFile::LayerNameMap& InfoFile::getLayerNames() const {
- return _layerNames;
-}
-
-std::size_t InfoFile::getLayerMappingCount() const {
- return _layerMappings.size();
-}
-
-const scene::LayerList& InfoFile::getNextLayerMapping() {
- // Check if we have a valid infofile
- if (!_isValid) {
- return _standardLayerList;
- }
-
- // Check if the node index is out of bounds
- if (_layerMappingIterator == _layerMappings.end()) {
- return _standardLayerList;
- }
-
- // Return the current list and increase the iterator afterwards
- return *(_layerMappingIterator++);
-}
-
-void InfoFile::parse()
-{
- // parse the header
- try {
- std::vector<std::string> parts;
- boost::algorithm::split(parts, HEADER_SEQUENCE, boost::algorithm::is_any_of(" "));
-
- // Parse the string "DarkRadiant Map Information File Version"
- for (std::size_t i = 0; i < parts.size(); i++) {
- _tok.assertNextToken(parts[i]);
- }
-
- float version = boost::lexical_cast<float>(_tok.nextToken());
-
- if (version != MAP_INFO_VERSION) {
- _isValid = false;
- throw parser::ParseException(_("Map Info File Version invalid"));
- }
- }
- catch (parser::ParseException& e) {
- rError()
- << "[InfoFile] Unable to parse info file header: "
- << e.what() << std::endl;
- _isValid = false;
- return;
- }
- catch (boost::bad_lexical_cast& e) {
- rError()
- << "[InfoFile] Unable to parse info file version: "
- << e.what() << std::endl;
- _isValid = false;
- return;
- }
-
- // The opening brace of the master block
- _tok.assertNextToken("{");
-
- parseInfoFileBody();
-
- // Set the layer mapping iterator to the beginning
- _layerMappingIterator = _layerMappings.begin();
-}
-
-void InfoFile::parseInfoFileBody()
-{
- while (_tok.hasMoreTokens())
- {
- std::string token = _tok.nextToken();
-
- if (token == LAYERS)
- {
- parseLayerNames();
- continue;
- }
-
- if (token == NODE_TO_LAYER_MAPPING)
- {
- parseNodeToLayerMapping();
- continue;
- }
-
- if (token == SELECTION_SETS)
- {
- parseSelectionSetInfo();
- continue;
- }
-
- if (token == "}")
- {
- break;
- }
-
- // Unknown token, try to ignore that block
- rWarning() << "Unknown keyword " << token << " encountered, will try to ignore this block." << std::endl;
-
- // We can only ignore a block if there is a block beginning curly brace
- _tok.assertNextToken("{");
-
- // Ignore the block
- int depth = 1;
-
- while (_tok.hasMoreTokens() && depth > 0)
- {
- std::string token = _tok.nextToken();
-
- if (token == "{")
- {
- depth++;
- }
- else if (token == "}")
- {
- depth--;
- }
- }
- }
-}
-
-void InfoFile::parseLayerNames()
-{
- // The opening brace
- _tok.assertNextToken("{");
-
- while (_tok.hasMoreTokens()) {
- std::string token = _tok.nextToken();
-
- if (token == LAYER) {
- // Get the ID
- std::string layerIDStr = _tok.nextToken();
- int layerID = string::convert<int>(layerIDStr);
-
- _tok.assertNextToken("{");
-
- // Assemble the name
- std::string name;
-
- token = _tok.nextToken();
- while (token != "}") {
- name += token;
- token = _tok.nextToken();
- }
-
- rMessage() << "[InfoFile]: Parsed layer #"
- << layerID << " with name " << name << std::endl;
-
- _layerNames.insert(LayerNameMap::value_type(layerID, name));
-
- continue;
- }
-
- if (token == "}") {
- break;
- }
- }
-}
-
-void InfoFile::parseNodeToLayerMapping()
-{
- // The opening brace
- _tok.assertNextToken("{");
-
- while (_tok.hasMoreTokens()) {
- std::string token = _tok.nextToken();
-
- if (token == NODE) {
- _tok.assertNextToken("{");
-
- // Create a new LayerList
- _layerMappings.push_back(scene::LayerList());
-
- while (_tok.hasMoreTokens()) {
- std::string nodeToken = _tok.nextToken();
-
- if (nodeToken == "}") {
- break;
- }
-
- // Add the ID to the list
- _layerMappings.back().insert(string::convert<int>(nodeToken));
- }
- }
-
- if (token == "}") {
- break;
- }
- }
-}
-
-void InfoFile::parseSelectionSetInfo()
-{
- _selectionSetInfo.clear();
-
- // SelectionSet 2 { "Stairs" } { (0 4076) (0 4077) (0 4078) (0 4079) (0 4309) (2) }
-
- // The opening brace
- _tok.assertNextToken("{");
-
- while (_tok.hasMoreTokens())
- {
- std::string token = _tok.nextToken();
-
- if (token == SELECTION_SET)
- {
- // Create a new SelectionSet info structure
- _selectionSetInfo.push_back(SelectionSetImportInfo());
-
- std::size_t selectionSetIndex = string::convert<std::size_t>(_tok.nextToken());
-
- rMessage() << "Parsing Selection Set #" << selectionSetIndex << std::endl;
-
- _tok.assertNextToken("{");
-
- // Parse the name, replacing the " placeholder with a proper quote
- _selectionSetInfo.back().name = boost::algorithm::replace_all_copy(_tok.nextToken(), """, "\"");
-
- _tok.assertNextToken("}");
-
- _tok.assertNextToken("{");
-
- while (_tok.hasMoreTokens())
- {
- std::string nextToken = _tok.nextToken();
-
- if (nextToken == "}") break;
-
- // If it's not a closing curly brace, it must be an opening parenthesis
- if (nextToken != "(")
- {
- throw parser::ParseException("InfoFile: Assertion failed: Required \"("
- "\", found \"" + nextToken + "\"");
- }
-
- // Expect one or two numbers now
- std::size_t entityNum = string::convert<std::size_t>(_tok.nextToken());
-
- nextToken = _tok.nextToken();
-
- if (nextToken == ")")
- {
- // Just the entity number, no primitive number
- _selectionSetInfo.back().nodeIndices.insert(
- SelectionSetImportInfo::IndexPair(entityNum, EMPTY_PRIMITVE_NUM));
- }
- else
- {
- // Primitive number is provided as well
- std::size_t primitiveNum = string::convert<std::size_t>(nextToken);
-
- // No more than 2 numbers are supported, so assume a closing parenthesis now
- _tok.assertNextToken(")");
-
- _selectionSetInfo.back().nodeIndices.insert(
- SelectionSetImportInfo::IndexPair(entityNum, primitiveNum));
- }
- }
- }
-
- if (token == "}") break;
- }
-}
-
-std::size_t InfoFile::getSelectionSetCount() const
-{
- return _selectionSetInfo.size();
-}
-
-// Traversal function for the parsed selection sets
-void InfoFile::foreachSelectionSetInfo(const std::function<void(const SelectionSetImportInfo&)>& functor)
-{
- std::for_each(_selectionSetInfo.begin(), _selectionSetInfo.end(), functor);
-}
-
-} // namespace map
diff --git a/radiant/map/InfoFile.h b/radiant/map/InfoFile.h
deleted file mode 100644
index d018d39..0000000
--- a/radiant/map/InfoFile.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#pragma once
-
-#include <map>
-#include "ilayer.h"
-#include "parser/DefTokeniser.h"
-
-namespace map
-{
-
-class InfoFile
-{
-public:
- // Tokens / Constants
- // The version of the map info file
- static const int MAP_INFO_VERSION = 2;
-
- // InfoFile tokens --------------------------------------------------
- static const char* const HEADER_SEQUENCE;
- static const char* const NODE_TO_LAYER_MAPPING;
- static const char* const LAYER;
- static const char* const LAYERS;
- static const char* const NODE;
- static const char* const SELECTION_SETS;
- static const char* const SELECTION_SET;
-
- // The internal placeholder number for "no primitive number"
- static std::size_t EMPTY_PRIMITVE_NUM;
-
- typedef std::map<int, std::string> LayerNameMap;
-
- struct SelectionSetImportInfo
- {
- // The name of this set
- std::string name;
-
- typedef std::pair<std::size_t, std::size_t> IndexPair;
-
- // The node indices, which will be resolved to nodes after import
- std::set<IndexPair> nodeIndices;
- };
-
-private:
- // The actual DefTokeniser to split the infoStream into pieces
- parser::BasicDefTokeniser<std::istream> _tok;
-
- // The list of layernames
- LayerNameMap _layerNames;
-
- typedef std::vector<scene::LayerList> LayerLists;
- LayerLists _layerMappings;
-
- // The standard list (node is part of layer 0)
- scene::LayerList _standardLayerList;
-
- // TRUE if the map info file was found to be valid
- bool _isValid;
-
- // The internal "iterator" into the NodeToLayerMapping vector
- LayerLists::const_iterator _layerMappingIterator;
-
- // Parsed selection set information
- std::vector<SelectionSetImportInfo> _selectionSetInfo;
-
-public:
- // Pass the input stream to the constructor
- InfoFile(std::istream& infoStream);
-
- // Parse the entire file
- void parse();
-
- // Get the parsed Layer list
- const LayerNameMap& getLayerNames() const;
-
- // Returns the next layer mapping. The internal iterator is increased by this call.
- // This allows the client code to treat this class like a LayerList input stream.
- const scene::LayerList& getNextLayerMapping();
-
- // Returns the number of parsed layer mappings
- std::size_t getLayerMappingCount() const;
-
- // Returns the number of selection sets
- std::size_t getSelectionSetCount() const;
-
- // Traversal function for the parsed selection sets
- void foreachSelectionSetInfo(const std::function<void(const SelectionSetImportInfo&)>& functor);
-
-private:
- void parseInfoFileBody();
-
- // Parses the Layers section
- void parseLayerNames();
-
- // SelectionSet information parser
- void parseSelectionSetInfo();
-
- void parseNodeToLayerMapping();
-};
-
-} // namespace map
diff --git a/radiant/map/Map.cpp b/radiant/map/Map.cpp
index e63dda4..04bed4f 100644
--- a/radiant/map/Map.cpp
+++ b/radiant/map/Map.cpp
@@ -6,15 +6,16 @@
#include "iscenegraph.h"
#include "idialogmanager.h"
#include "ieventmanager.h"
-#include "iundo.h"
#include "ifilesystem.h"
#include "ifiletypes.h"
+#include "iselectiongroup.h"
#include "ifilter.h"
#include "icounter.h"
#include "iradiant.h"
#include "imainframe.h"
#include "imapresource.h"
-#include "iselectionset.h"
+#include "iaasfile.h"
+#include "igame.h"
#include "registry/registry.h"
#include "stream/textfilestream.h"
@@ -28,12 +29,10 @@
#include "brush/BrushModule.h"
#include "xyview/GlobalXYWnd.h"
#include "camera/GlobalCamera.h"
-#include "map/AutoSaver.h"
#include "scene/BasicRootNode.h"
#include "map/MapFileManager.h"
#include "map/MapPositionManager.h"
#include "map/PointFile.h"
-#include "map/RegionManager.h"
#include "map/RootNode.h"
#include "map/MapResource.h"
#include "map/algorithm/Clone.h"
@@ -46,135 +45,60 @@
#include "ui/layers/LayerControlDialog.h"
#include "ui/prefabselector/PrefabSelector.h"
#include "selection/algorithm/Primitives.h"
+#include "selection/algorithm/Group.h"
#include "selection/shaderclipboard/ShaderClipboard.h"
#include "modulesystem/ModuleRegistry.h"
#include "modulesystem/StaticModule.h"
+#include "RenderableAasFile.h"
#include <boost/format.hpp>
#include "algorithm/ChildPrimitives.h"
-namespace map {
+namespace map
+{
- namespace {
+ namespace
+ {
const char* const MAP_UNNAMED_STRING = N_("unnamed.map");
const char* const GKEY_LAST_CAM_POSITION = "/mapFormat/lastCameraPositionKey";
const char* const GKEY_LAST_CAM_ANGLE = "/mapFormat/lastCameraAngleKey";
const char* const GKEY_PLAYER_START_ECLASS = "/mapFormat/playerStartPoint";
const char* const GKEY_PLAYER_HEIGHT = "/defaults/playerHeight";
-
- // Traverse all entities and store the first worldspawn into the map
- class MapWorldspawnFinder :
- public scene::NodeVisitor
- {
- public:
- virtual bool pre(const scene::INodePtr& node) {
- if (node_is_worldspawn(node)) {
- if (GlobalMap().getWorldspawn() == NULL) {
- GlobalMap().setWorldspawn(node);
- }
- }
- return false;
- }
- };
-
- class CollectAllWalker :
- public scene::NodeVisitor
- {
- scene::INodePtr _root;
- std::vector<scene::INodePtr>& _nodes;
- public:
- CollectAllWalker(scene::INodePtr root, std::vector<scene::INodePtr>& nodes) :
- _root(root),
- _nodes(nodes)
- {}
-
- ~CollectAllWalker() {
- for (std::vector<scene::INodePtr>::iterator i = _nodes.begin();
- i != _nodes.end(); ++i)
- {
- _root->removeChildNode(*i);
- }
- }
-
- virtual bool pre(const scene::INodePtr& node) {
- // Add this to the list
- _nodes.push_back(node);
- // Don't traverse deeper than first level
- return false;
- }
- };
-
- void Node_insertChildFirst(scene::INodePtr parent, scene::INodePtr child) {
- // Create a container to collect all the existing entities in the scenegraph
- std::vector<scene::INodePtr> nodes;
-
- // Collect all the child nodes of <parent> and move them into the container
- {
- CollectAllWalker visitor(parent, nodes);
- parent->traverseChildren(visitor);
-
- // the CollectAllWalker removes the nodes from the parent on destruction
- }
-
- // Now that the <parent> is empty, insert the worldspawn as first child
- parent->addChildNode(child);
-
- // Insert all the nodes again
- for (std::vector<scene::INodePtr>::iterator i = nodes.begin();
- i != nodes.end();
- ++i)
- {
- parent->addChildNode(*i);
- }
- }
-
- scene::INodePtr createWorldspawn()
- {
- scene::INodePtr worldspawn(GlobalEntityCreator().createEntity(GlobalEntityClassManager().findOrInsert("worldspawn", true)));
- Node_insertChildFirst(GlobalSceneGraph().root(), worldspawn);
- return worldspawn;
- }
}
Map::Map() :
_lastCopyMapName(""),
- m_valid(false),
_saveInProgress(false)
{
_mapSaveTimer.Pause();
}
-void Map::realiseResource() {
- if (m_resource != NULL) {
- m_resource->realise();
- }
-}
+void Map::loadMapResourceFromPath(const std::string& path)
+{
+ // Map loading started
+ signal_mapEvent().emit(MapLoading);
-void Map::unrealiseResource() {
- if (m_resource != NULL) {
- m_resource->unrealise();
- }
-}
+ _resource = GlobalMapResourceManager().loadFromPath(_mapName);
-void Map::onResourceRealise() {
- if (m_resource == NULL) {
+ if (!_resource)
+ {
return;
}
- if (isUnnamed() || !m_resource->load())
+ if (isUnnamed() || !_resource->load())
{
// Map is unnamed or load failed, reset map resource node to empty
- m_resource->setNode(std::make_shared<RootNode>(""));
+ _resource->setNode(std::make_shared<RootNode>(""));
- m_resource->getNode()->getUndoChangeTracker().save();
+ _resource->getNode()->getUndoChangeTracker().save();
// Rename the map to "unnamed" in any case to avoid overwriting the failed map
setMapName(_(MAP_UNNAMED_STRING));
}
// Take the new node and insert it as map root
- GlobalSceneGraph().setRoot(m_resource->getNode());
+ GlobalSceneGraph().setRoot(_resource->getNode());
// Associate the Scenegaph with the global RenderSystem
// This usually takes a while since all editor textures are loaded - display a dialog to inform the user
@@ -185,38 +109,8 @@ void Map::onResourceRealise() {
module::GlobalModuleRegistry().getModule(MODULE_RENDERSYSTEM)));
}
- AutoSaver().clearChanges();
-
- setValid(true);
-}
-
-void Map::onResourceUnrealise() {
- if(m_resource != 0)
- {
- setValid(false);
- setWorldspawn(scene::INodePtr());
-
- GlobalUndoSystem().clear();
- GlobalSelectionSetManager().deleteAllSelectionSets();
-
- GlobalSceneGraph().setRoot(scene::IMapRootNodePtr());
- }
-}
-
-sigc::signal<void> Map::signal_mapValidityChanged() const
-{
- return _sigMapValidityChanged;
-}
-
-void Map::setValid(bool valid)
-{
- m_valid = valid;
- _sigMapValidityChanged();
-}
-
-bool Map::isValid() const
-{
- return m_valid;
+ // Map loading finished, emit the signal
+ signal_mapEvent().emit(MapLoaded);
}
void Map::updateTitle()
@@ -239,8 +133,9 @@ void Map::setMapName(const std::string& newName) {
_mapName = newName;
// Update the map resource's root node, if there is one
- if (m_resource != NULL) {
- m_resource->rename(newName);
+ if (_resource)
+ {
+ _resource->rename(newName);
}
// Update the title of the main window
@@ -255,18 +150,27 @@ bool Map::isUnnamed() const {
return _mapName == _(MAP_UNNAMED_STRING);
}
-void Map::setWorldspawn(scene::INodePtr node) {
- m_world_node = node;
+void Map::setWorldspawn(const scene::INodePtr& node)
+{
+ _worldSpawnNode = node;
}
-scene::INodePtr Map::getWorldspawn() {
- return m_world_node;
+Map::MapEventSignal Map::signal_mapEvent() const
+{
+ return _mapEvent;
}
-scene::IMapRootNodePtr Map::getRoot() {
- if (m_resource != NULL) {
+const scene::INodePtr& Map::getWorldspawn()
+{
+ return _worldSpawnNode;
+}
+
+scene::IMapRootNodePtr Map::getRoot()
+{
+ if (_resource)
+ {
// Try to cast the node onto a root node and return
- return std::dynamic_pointer_cast<scene::IMapRootNode>(m_resource->getNode());
+ return std::dynamic_pointer_cast<scene::IMapRootNode>(_resource->getNode());
}
return scene::IMapRootNodePtr();
@@ -291,24 +195,20 @@ MapFormatPtr Map::getFormat()
}
// free all map elements, reinitialize the structures that depend on them
-void Map::freeMap() {
- map::PointFile::Instance().clear();
+void Map::freeMap()
+{
+ // Fire the map unloading event,
+ // This will de-select stuff, clear the pointfile, etc.
+ signal_mapEvent().emit(MapUnloading);
- GlobalSelectionSystem().setSelectedAll(false);
- GlobalSelectionSystem().setSelectedAllComponents(false);
+ setWorldspawn(scene::INodePtr());
- GlobalShaderClipboard().clear();
- GlobalRegion().clear();
+ GlobalSceneGraph().setRoot(scene::IMapRootNodePtr());
- if (m_resource)
- {
- m_resource->removeObserver(*this);
- }
+ signal_mapEvent().emit(MapUnloaded);
// Reset the resource pointer
- m_resource = IMapResourcePtr();
-
- GlobalLayerSystem().reset();
+ _resource.reset();
}
bool Map::isModified() const {
@@ -336,9 +236,9 @@ void Map::removeCameraPosition() {
const std::string keyLastCamPos = game::current::getValue<std::string>(GKEY_LAST_CAM_POSITION);
const std::string keyLastCamAngle = game::current::getValue<std::string>(GKEY_LAST_CAM_ANGLE);
- if (m_world_node != NULL) {
+ if (_worldSpawnNode != NULL) {
// Retrieve the entity from the worldspawn node
- Entity* worldspawn = Node_getEntity(m_world_node);
+ Entity* worldspawn = Node_getEntity(_worldSpawnNode);
assert(worldspawn != NULL); // This must succeed
worldspawn->setKeyValue(keyLastCamPos, "");
@@ -353,9 +253,9 @@ void Map::saveCameraPosition()
const std::string keyLastCamPos = game::current::getValue<std::string>(GKEY_LAST_CAM_POSITION);
const std::string keyLastCamAngle = game::current::getValue<std::string>(GKEY_LAST_CAM_ANGLE);
- if (m_world_node != NULL) {
+ if (_worldSpawnNode != NULL) {
// Retrieve the entity from the worldspawn node
- Entity* worldspawn = Node_getEntity(m_world_node);
+ Entity* worldspawn = Node_getEntity(_worldSpawnNode);
assert(worldspawn != NULL); // This must succeed
ui::CamWndPtr camWnd = GlobalCamera().getActiveCamWnd();
@@ -379,9 +279,9 @@ void Map::gotoStartPosition()
Vector3 angles(0,0,0);
Vector3 origin(0,0,0);
- if (m_world_node != NULL) {
+ if (_worldSpawnNode != NULL) {
// Retrieve the entity from the worldspawn node
- Entity* worldspawn = Node_getEntity(m_world_node);
+ Entity* worldspawn = Node_getEntity(_worldSpawnNode);
assert(worldspawn != NULL); // This must succeed
// Try to find a saved "last camera position"
@@ -392,7 +292,7 @@ void Map::gotoStartPosition()
// Construct the vector out of the std::string
origin = string::convert<Vector3>(savedOrigin);
- Vector3 angles = string::convert<Vector3>(
+ angles = string::convert<Vector3>(
worldspawn->getKeyValue(keyLastCamAngle)
);
@@ -434,26 +334,49 @@ void Map::gotoStartPosition()
focusViews(origin, angles);
}
-scene::INodePtr Map::findWorldspawn() {
- // Clear the current worldspawn node
- setWorldspawn(scene::INodePtr());
+scene::INodePtr Map::findWorldspawn()
+{
+ scene::INodePtr worldspawn;
// Traverse the scenegraph and search for the worldspawn
- MapWorldspawnFinder visitor;
- GlobalSceneGraph().root()->traverseChildren(visitor);
+ GlobalSceneGraph().root()->foreachNode([&](const scene::INodePtr& node)
+ {
+ if (Node_isWorldspawn(node))
+ {
+ worldspawn = node;
+ return false; // done traversing
+ }
+
+ return true;
+ });
+
+ // Set the worldspawn, might be null if nothing was found
+ setWorldspawn(worldspawn);
- return getWorldspawn();
+ return worldspawn;
}
-void Map::updateWorldspawn() {
- if (findWorldspawn() == NULL) {
- setWorldspawn(createWorldspawn());
- }
+scene::INodePtr Map::createWorldspawn()
+{
+ scene::INodePtr worldspawn(GlobalEntityCreator().createEntity(
+ GlobalEntityClassManager().findOrInsert("worldspawn", true)));
+
+ // We want the world spawn entity to go for the pole position
+ GlobalSceneGraph().root()->addChildNode(worldspawn);
+
+ return worldspawn;
}
-scene::INodePtr Map::findOrInsertWorldspawn() {
- updateWorldspawn();
- return getWorldspawn();
+const scene::INodePtr& Map::findOrInsertWorldspawn()
+{
+ // If we don't know any worldspawn yet, and can't find one either,
+ // let's create one afresh
+ if (!_worldSpawnNode && findWorldspawn() == nullptr)
+ {
+ setWorldspawn(createWorldspawn());
+ }
+
+ return _worldSpawnNode;
}
void Map::load(const std::string& filename) {
@@ -461,20 +384,13 @@ void Map::load(const std::string& filename) {
setMapName(filename);
- // Reset all layers before loading the file
- GlobalLayerSystem().reset();
- GlobalSelectionSystem().setSelectedAll(false);
-
{
wxutil::ScopeTimer timer("map load");
- m_resource = GlobalMapResourceManager().capture(_mapName);
- // greebo: Add the observer, this usually triggers a onResourceRealise() call.
- m_resource->addObserver(*this);
+ loadMapResourceFromPath(_mapName);
// Traverse the scenegraph and find the worldspawn
- MapWorldspawnFinder finder;
- GlobalSceneGraph().root()->traverseChildren(finder);
+ findWorldspawn();
}
rMessage() << "--- LoadMapFile ---\n";
@@ -492,9 +408,6 @@ void Map::load(const std::string& filename) {
// Remove them, so that the user doesn't get bothered with them
GlobalMapPosition().removePositions();
- // Disable the region to make sure
- GlobalRegion().disable();
-
// Clear the shaderclipboard, the references are most probably invalid now
GlobalShaderClipboard().clear();
@@ -528,7 +441,7 @@ bool Map::save(const MapFormatPtr& mapFormat)
wxutil::ScopeTimer timer("map save");
// Save the actual map resource
- bool success = m_resource->save(mapFormat);
+ bool success = _resource->save(mapFormat);
// Remove the saved camera position
removeCameraPosition();
@@ -554,8 +467,7 @@ bool Map::save(const MapFormatPtr& mapFormat)
void Map::createNew() {
setMapName(_(MAP_UNNAMED_STRING));
- m_resource = GlobalMapResourceManager().capture(_mapName);
- m_resource->addObserver(*this);
+ loadMapResourceFromPath(_mapName);
SceneChangeNotify();
@@ -571,7 +483,7 @@ bool Map::import(const std::string& filename)
bool success = false;
{
- IMapResourcePtr resource = GlobalMapResourceManager().capture(filename);
+ IMapResourcePtr resource = GlobalMapResourceManager().loadFromPath(filename);
if (resource->load())
{
@@ -795,9 +707,9 @@ void Map::loadPrefabAt(const Vector3& targetCoords)
/*MapFileSelection fileInfo =
MapFileManager::getMapFileSelection(true, _("Load Prefab"), "prefab");*/
- std::string path = ui::PrefabSelector::ChoosePrefab();
+ ui::PrefabSelector::Result result = ui::PrefabSelector::ChoosePrefab();
- if (!path.empty())
+ if (!result.prefabPath.empty())
{
UndoableCommand undo("loadPrefabAt");
@@ -805,7 +717,7 @@ void Map::loadPrefabAt(const Vector3& targetCoords)
GlobalSelectionSystem().setSelectedAll(false);
// Now import the prefab (imported items get selected)
- import(path);
+ import(result.prefabPath);
// Switch texture lock on
bool prevTexLockState = GlobalBrush().textureLockEnabled();
@@ -816,6 +728,20 @@ void Map::loadPrefabAt(const Vector3& targetCoords)
// Revert to previous state
GlobalBrush().setTextureLock(prevTexLockState);
+
+ // Check whether we should group the prefab parts
+ if (result.insertAsGroup && GlobalSelectionSystem().countSelected() > 1)
+ {
+ try
+ {
+ selection::algorithm::groupSelected();
+ }
+ catch (selection::algorithm::CommandNotAvailableException& ex)
+ {
+ // Ignore grouping errors on prefab insert, just log the message
+ rError() << "Error grouping the prefab: " << ex.what() << std::endl;
+ }
+ }
}
}
@@ -850,11 +776,10 @@ void Map::registerCommands()
}
// Static command targets
-void Map::newMap(const cmd::ArgumentList& args) {
- if (GlobalMap().askForSave(_("New Map"))) {
- // Turn regioning off when starting a new map
- GlobalRegion().disable();
-
+void Map::newMap(const cmd::ArgumentList& args)
+{
+ if (GlobalMap().askForSave(_("New Map")))
+ {
GlobalMap().freeMap();
GlobalMap().createNew();
}
@@ -938,7 +863,7 @@ void Map::rename(const std::string& filename) {
SceneChangeNotify();
}
else {
- m_resource->save();
+ _resource->save();
setModified(false);
}
}
@@ -1032,11 +957,14 @@ const std::string& Map::getName() const {
return _name;
}
-const StringSet& Map::getDependencies() const {
+const StringSet& Map::getDependencies() const
+{
static StringSet _dependencies;
- if (_dependencies.empty()) {
+ if (_dependencies.empty())
+ {
_dependencies.insert(MODULE_RADIANT);
+ _dependencies.insert(MODULE_GAMEMANAGER);
}
return _dependencies;
@@ -1058,9 +986,6 @@ void Map::initialiseModule(const ApplicationContext& ctx)
// Add the Map-related commands to the EventManager
registerCommands();
- // Add the region-related commands to the EventManager
- RegionManager::initialiseCommands();
-
// Add the map position commands to the EventManager
GlobalMapPosition().initialise();
diff --git a/radiant/map/Map.h b/radiant/map/Map.h
index 72b9e3f..a688c70 100644
--- a/radiant/map/Map.h
+++ b/radiant/map/Map.h
@@ -19,8 +19,7 @@ class TextInputStream;
namespace map {
class Map :
- public IMap,
- public IMapResource::Observer
+ public IMap
{
// The map name
std::string _mapName;
@@ -29,14 +28,11 @@ class Map :
std::string _lastCopyMapName;
// Pointer to the resource for this map
- IMapResourcePtr m_resource;
+ IMapResourcePtr _resource;
- bool m_valid;
bool m_modified;
- sigc::signal<void> _sigMapValidityChanged;
-
- scene::INodePtr m_world_node; // "classname" "worldspawn" !
+ scene::INodePtr _worldSpawnNode; // "classname" "worldspawn" !
bool _saveInProgress;
@@ -47,26 +43,23 @@ class Map :
// messages
wxStopWatch _mapSaveTimer;
-private:
-
- // If no worldspawn can be found in the scenegraph, this creates one
- void updateWorldspawn();
+ MapEventSignal _mapEvent;
+private:
std::string getSaveConfirmationText() const;
public:
Map();
- virtual scene::INodePtr getWorldspawn() override;
+ virtual MapEventSignal signal_mapEvent() const override;
+ virtual const scene::INodePtr& getWorldspawn() override;
+ virtual const scene::INodePtr& findOrInsertWorldspawn() override;
virtual scene::IMapRootNodePtr getRoot() override;
// RegisterableModule implementation
- virtual const std::string& getName() const;
- virtual const StringSet& getDependencies() const;
- virtual void initialiseModule(const ApplicationContext& ctx);
-
- void realiseResource();
- void unrealiseResource();
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
/** greebo: Returns true if the map has not been named yet.
*/
@@ -150,14 +143,6 @@ public:
// free all map elements, reinitialize the structures that depend on them
void freeMap();
- // Resource::Observer implementation
- void onResourceRealise();
- void onResourceUnrealise();
-
- // Accessor methods for the "valid" flag
- void setValid(bool valid);
- bool isValid() const;
-
/** greebo: Returns true if the map has unsaved changes.
*/
bool isModified() const;
@@ -165,24 +150,11 @@ public:
// Sets the modified status of this map
void setModified(bool modifiedFlag);
- // Signal emitted when the map validity changes
- sigc::signal<void> signal_mapValidityChanged() const;
-
// Updates the window title of the mainframe
void updateTitle();
// Accessor methods for the worldspawn node
- void setWorldspawn(scene::INodePtr node);
-
- /** greebo: This retrieves the worldspawn node of this map.
- * If no worldspawn can be found, this creates one.
- */
- scene::INodePtr findOrInsertWorldspawn();
-
- /** greebo: Tries to locate the worldspawn in the global scenegraph
- * Returns NULL (empty shared_ptr) if nothing is found.
- */
- scene::INodePtr findWorldspawn();
+ void setWorldspawn(const scene::INodePtr& node);
/** greebo: Returns the map format for this map
*/
@@ -241,6 +213,19 @@ public:
static void loadPrefab(const cmd::ArgumentList& args);
static void saveSelectedAsPrefab(const cmd::ArgumentList& args);
+private:
+ /**
+ * greebo: Tries to locate the worldspawn in the global scenegraph and
+ * stores it into the local member variable.
+ * Returns the node that was found (can be an empty ptr).
+ */
+ scene::INodePtr findWorldspawn();
+
+ // Creates a fresh worldspawn node and inserts it into the root scene node
+ scene::INodePtr createWorldspawn();
+
+ void loadMapResourceFromPath(const std::string& path);
+
}; // class Map
} // namespace map
diff --git a/radiant/map/MapResource.cpp b/radiant/map/MapResource.cpp
index b778dec..688ebf7 100644
--- a/radiant/map/MapResource.cpp
+++ b/radiant/map/MapResource.cpp
@@ -11,6 +11,8 @@
#include "ifilesystem.h"
#include "imainframe.h"
#include "iregistry.h"
+#include "imapinfofile.h"
+
#include "map/Map.h"
#include "map/RootNode.h"
#include "mapfile.h"
@@ -27,15 +29,13 @@
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
-#include "InfoFile.h"
+#include "infofile/InfoFile.h"
#include "string/string.h"
#include "algorithm/MapImporter.h"
#include "algorithm/MapExporter.h"
-#include "algorithm/InfoFileExporter.h"
-#include "algorithm/AssignLayerMappingWalker.h"
+#include "infofile/InfoFileExporter.h"
#include "algorithm/ChildPrimitives.h"
-#include "scene/LayerValidityCheckWalker.h"
namespace fs = boost::filesystem;
@@ -85,9 +85,7 @@ std::string MapResource::_infoFileExt;
// Constructor
MapResource::MapResource(const std::string& name) :
_originalName(name),
- _type(os::getExtension(name)),
- _modified(0),
- _realised(false)
+ _type(os::getExtension(name))
{
// Initialise the paths, this is all needed for realisation
_path = rootPath(_originalName);
@@ -104,12 +102,6 @@ MapResource::MapResource(const std::string& name) :
}
}
-MapResource::~MapResource() {
- if (realised()) {
- unrealise();
- }
-}
-
void MapResource::rename(const std::string& fullPath)
{
// Save the paths locally and split them into parts
@@ -124,8 +116,6 @@ void MapResource::rename(const std::string& fullPath)
bool MapResource::load()
{
- ASSERT_MESSAGE(realised(), "resource not realised");
-
if (!_mapRoot)
{
// Map not loaded yet, acquire map root node from loader
@@ -138,12 +128,6 @@ bool MapResource::load()
return _mapRoot != nullptr;
}
-/**
- * Save this resource (only for map resources).
- *
- * @returns
- * true if the resource was saved, false otherwise.
- */
bool MapResource::save(const MapFormatPtr& mapFormat)
{
// For saving, take the default map format for this game type
@@ -290,59 +274,8 @@ void MapResource::setNode(const scene::IMapRootNodePtr& node)
connectMap();
}
-void MapResource::addObserver(Observer& observer) {
- if (realised()) {
- observer.onResourceRealise();
- }
- _observers.insert(&observer);
-}
-
-void MapResource::removeObserver(Observer& observer) {
- if (realised()) {
- observer.onResourceUnrealise();
- }
- _observers.erase(&observer);
-}
-
-bool MapResource::realised() {
- return _realised;
-}
-
-// Realise this MapResource
-void MapResource::realise() {
- if (_realised) {
- return; // nothing to do
- }
-
- _realised = true;
-
- // Realise the observers
- for (ResourceObserverList::iterator i = _observers.begin();
- i != _observers.end(); i++)
- {
- (*i)->onResourceRealise();
- }
-}
-
-void MapResource::unrealise() {
- if (!_realised) {
- return; // nothing to do
- }
-
- _realised = false;
-
- // Realise the observers
- for (ResourceObserverList::iterator i = _observers.begin();
- i != _observers.end(); i++)
- {
- (*i)->onResourceUnrealise();
- }
-
- //rMessage() << "MapResource::unrealise: " << _path.c_str() << _name.c_str() << "\n";
- _mapRoot.reset();
-}
-
-void MapResource::onMapChanged() {
+void MapResource::onMapChanged()
+{
GlobalMap().setModified(true);
}
@@ -355,33 +288,14 @@ void MapResource::connectMap()
}
}
-std::time_t MapResource::modified() const {
- std::string fullpath = _path + _name;
- return file_modified(fullpath.c_str());
-}
-
void MapResource::mapSave()
{
- _modified = modified();
-
if (_mapRoot)
{
_mapRoot->getUndoChangeTracker().save();
}
}
-bool MapResource::isModified() const {
- // had or has an absolute path // AND disk timestamp changed
- return (!_path.empty() && _modified != modified())
- || !path_equal(rootPath(_originalName).c_str(), _path.c_str()); // OR absolute vfs-root changed
-}
-
-void MapResource::reload()
-{
- unrealise();
- realise();
-}
-
MapFormatPtr MapResource::determineMapFormat(std::istream& stream)
{
// Get all registered map formats
@@ -389,15 +303,15 @@ MapFormatPtr MapResource::determineMapFormat(std::istream& stream)
MapFormatPtr format;
- for (std::set<MapFormatPtr>::const_iterator f = availableFormats.begin(); f != availableFormats.end(); ++f)
+ for (const MapFormatPtr& candidate : availableFormats)
{
// Rewind the stream before passing it to the format for testing
// Map format valid, rewind the stream
stream.seekg(0, std::ios_base::beg);
- if ((*f)->canLoad(stream))
+ if (candidate->canLoad(stream))
{
- format = *f;
+ format = candidate;
break;
}
}
@@ -410,72 +324,43 @@ MapFormatPtr MapResource::determineMapFormat(std::istream& stream)
RootNodePtr MapResource::loadMapNode()
{
+ RootNodePtr rootNode;
+
// greebo: Check if we have valid settings
// The _path might be empty if we're loading from a folder outside the mod
if (_name.empty() && _type.empty())
{
- return RootNodePtr();
+ return rootNode;
}
- // Build the map path
- std::string fullpath = _path + _name;
-
- if (path_is_absolute(fullpath.c_str()))
+ try
{
- rMessage() << "Open file " << fullpath << " for determining the map format...";
-
- TextFileInputStream file(fullpath);
+ // Build the map path
+ std::string fullpath = _path + _name;
- if (file.failed())
+ // Open a stream (from physical file or VFS)
+ openFileStream(fullpath, [&](std::istream& mapStream)
{
- rError() << "failure" << std::endl;
-
- wxutil::Messagebox::ShowError(
- (boost::format(_("Failure opening map file:\n%s")) % fullpath).str());
-
- return RootNodePtr();
- }
-
- std::istream mapStream(&file);
- return loadMapNodeFromStream(mapStream, fullpath);
+ rootNode = loadMapNodeFromStream(mapStream, fullpath);
+ });
}
- else
+ catch (std::runtime_error& ex)
{
- // Not an absolute path, might as well be a VFS path, so try to load it from the PAKs
- rMessage() << "Open file " << fullpath << " from VFS for determining the map format...";
-
- ArchiveTextFilePtr vfsFile = GlobalFileSystem().openTextFile(fullpath);
-
- if (!vfsFile)
- {
- rError() << "Could not find file in VFS either: " << fullpath << std::endl;
- return RootNodePtr();
- }
-
- std::istream mapStream(&(vfsFile->getInputStream()));
-
- // Deflated text files don't support stream positioning (seeking)
- // so load everything into one large string and create a new buffer
- std::stringstream stringStream;
- stringStream << mapStream.rdbuf();
-
- return loadMapNodeFromStream(stringStream, fullpath);
+ wxutil::Messagebox::ShowError(ex.what());
}
+
+ return rootNode;
}
RootNodePtr MapResource::loadMapNodeFromStream(std::istream& stream, const std::string& fullpath)
{
- rMessage() << "success" << std::endl;
-
// Get the mapformat
MapFormatPtr format = determineMapFormat(stream);
if (format == NULL)
{
- wxutil::Messagebox::ShowError(
+ throw std::runtime_error(
(boost::format(_("Could not determine map format of file:\n%s")) % fullpath).str());
-
- return RootNodePtr();
}
// Map format valid, rewind the stream
@@ -515,84 +400,7 @@ bool MapResource::loadFile(std::istream& mapStream, const MapFormat& format, con
}
// Check for an additional info file
- std::string infoFilename(filename.substr(0, filename.rfind('.')));
- infoFilename += game::current::getValue<std::string>(GKEY_INFO_FILE_EXTENSION);
-
- std::ifstream infoFileStream(infoFilename.c_str());
-
- if (infoFileStream.is_open())
- {
- rMessage() << " found information file... ";
- }
-
- rMessage() << "success" << std::endl;
-
- // Read the infofile
- InfoFile infoFile(infoFileStream);
-
- try
- {
- // Start parsing, this will throw if any errors occur
- infoFile.parse();
-
- // Create the layers according to the data found in the map information file
- const InfoFile::LayerNameMap& layers = infoFile.getLayerNames();
-
- for (InfoFile::LayerNameMap::const_iterator i = layers.begin();
- i != layers.end(); ++i)
- {
- // Create the named layer with the saved ID
- GlobalLayerSystem().createLayer(i->second, i->first);
- }
-
- // Now that the graph is in place, assign the layers
- AssignLayerMappingWalker walker(infoFile);
- root->traverseChildren(walker);
-
- rMessage() << "Sanity-checking the layer assignments...";
-
- // Sanity-check the layer mapping, it's possible that some .darkradiant
- // files are mapping nodes to non-existent layer IDs
- scene::LayerValidityCheckWalker checker;
- root->traverseChildren(checker);
-
- rMessage() << "done, had to fix " << checker.getNumFixed() << " assignments." << std::endl;
-
- // Remove all selection sets, there shouldn't be many left at this point
- GlobalSelectionSetManager().deleteAllSelectionSets();
-
- // Re-construct the selection sets
- infoFile.foreachSelectionSetInfo([&] (const InfoFile::SelectionSetImportInfo& info)
- {
- selection::ISelectionSetPtr set = GlobalSelectionSetManager().createSelectionSet(info.name);
-
- std::size_t failedNodes = 0;
-
- std::for_each(info.nodeIndices.begin(), info.nodeIndices.end(),
- [&] (const InfoFile::SelectionSetImportInfo::IndexPair& indexPair)
- {
- scene::INodePtr node = importFilter.getNodeByIndexPair(indexPair);
-
- if (node)
- {
- set->addNode(node);
- }
- else
- {
- failedNodes++;
- }
- });
-
- if (failedNodes > 0)
- {
- rWarning() << "Couldn't resolve " << failedNodes << " nodes in selection set " << set->getName() << std::endl;
- }
- });
- }
- catch (parser::ParseException& e)
- {
- rError() << "[MapResource] Unable to parse info file: " << e.what() << std::endl;
- }
+ loadInfoFile(root, filename, importFilter.getNodeMap());
return true;
}
@@ -621,12 +429,92 @@ bool MapResource::loadFile(std::istream& mapStream, const MapFormat& format, con
}
}
-std::string MapResource::getTemporaryFileExtension()
+void MapResource::loadInfoFile(const RootNodePtr& root, const std::string& filename, const NodeIndexMap& nodeMap)
{
- time_t localtime;
- time(&localtime);
+ try
+ {
+ std::string infoFilename(filename.substr(0, filename.rfind('.')));
+ infoFilename += game::current::getValue<std::string>(GKEY_INFO_FILE_EXTENSION);
- return string::to_string(localtime);
+ openFileStream(infoFilename, [&](std::istream& infoFileStream)
+ {
+ loadInfoFileFromStream(infoFileStream, root, nodeMap);
+ });
+ }
+ catch (std::runtime_error& ex)
+ {
+ rWarning() << ex.what() << std::endl;
+ }
+}
+
+void MapResource::loadInfoFileFromStream(std::istream& infoFileStream, const RootNodePtr& root, const NodeIndexMap& nodeMap)
+{
+ if (!infoFileStream.good())
+ {
+ rError() << "[MapResource] No valid info file stream" << std::endl;
+ return;
+ }
+
+ rMessage() << "Parsing info file..." << std::endl;
+
+ try
+ {
+ // Read the infofile
+ InfoFile infoFile(infoFileStream, root, nodeMap);
+
+ // Start parsing, this will throw if any errors occur
+ infoFile.parse();
+ }
+ catch (parser::ParseException& e)
+ {
+ rError() << "[MapResource] Unable to parse info file: " << e.what() << std::endl;
+ }
+}
+
+void MapResource::openFileStream(const std::string& path, const std::function<void(std::istream&)>& streamProcessor)
+{
+ if (path_is_absolute(path.c_str()))
+ {
+ rMessage() << "Open file " << path << " from filesystem...";
+
+ TextFileInputStream file(path);
+
+ if (file.failed())
+ {
+ rError() << "failure" << std::endl;
+ throw std::runtime_error((boost::format(_("Failure opening file:\n%s")) % path).str());
+ }
+
+ std::istream stream(&file);
+
+ rMessage() << "success." << std::endl;
+
+ streamProcessor(stream);
+ }
+ else
+ {
+ // Not an absolute path, might as well be a VFS path, so try to load it from the PAKs
+ rMessage() << "Trying to open file " << path << " from VFS...";
+
+ ArchiveTextFilePtr vfsFile = GlobalFileSystem().openTextFile(path);
+
+ if (!vfsFile)
+ {
+ rError() << "failure" << std::endl;
+ throw std::runtime_error((boost::format(_("Failure opening file:\n%s")) % path).str());
+ }
+
+ rMessage() << "success." << std::endl;
+
+ std::istream vfsStream(&(vfsFile->getInputStream()));
+
+ // Deflated text files don't support stream positioning (seeking)
+ // so load everything into one large string and create a new buffer
+ std::stringstream stringStream;
+ stringStream << vfsStream.rdbuf();
+
+ streamProcessor(stringStream);
+ }
}
bool MapResource::checkIsWriteable(const boost::filesystem::path& path)
diff --git a/radiant/map/MapResource.h b/radiant/map/MapResource.h
index b22ba2c..d86a978 100644
--- a/radiant/map/MapResource.h
+++ b/radiant/map/MapResource.h
@@ -2,6 +2,7 @@
#include "imapresource.h"
#include "imapformat.h"
+#include "imapinfofile.h"
#include "imodel.h"
#include "imap.h"
#include <set>
@@ -15,6 +16,7 @@ class MapResource :
public IMapResource,
public boost::noncopyable
{
+private:
RootNodePtr _mapRoot;
// Name given during construction
@@ -28,62 +30,26 @@ class MapResource :
// Type of resource "map"
std::string _type;
- typedef std::set<IMapResource::Observer*> ResourceObserverList;
- ResourceObserverList _observers;
-
- std::time_t _modified;
- bool _realised;
-
public:
// Constructor
MapResource(const std::string& name);
- virtual ~MapResource();
-
- void rename(const std::string& fullPath);
+ void rename(const std::string& fullPath) override;
- bool load();
-
- /**
- * Save this resource (only for map resources).
- *
- * It's possible to pass a mapformat to be used for saving. If the map
- * format argument is omitted, the format corresponding to the current
- * game type is used.
- *
- * @returns
- * true if the resource was saved, false otherwise.
- */
- bool save(const MapFormatPtr& mapFormat = MapFormatPtr());
-
- // Reloads from disk
- void reload();
+ bool load() override;
+ bool save(const MapFormatPtr& mapFormat = MapFormatPtr()) override;
scene::IMapRootNodePtr getNode() override;
void setNode(const scene::IMapRootNodePtr& node) override;
- virtual void addObserver(Observer& observer);
- virtual void removeObserver(Observer& observer);
-
- bool realised();
-
- // Realise this MapResource
- void realise();
- void unrealise();
-
- std::time_t modified() const;
- void mapSave();
-
- bool isModified() const;
- void refresh();
-
- void onMapChanged();
-
// Save the map contents to the given filename using the given MapFormat export module
static bool saveFile(const MapFormat& format, const scene::INodePtr& root,
const GraphTraversalFunc& traverse, const std::string& filename);
private:
+ void mapSave();
+ void onMapChanged();
+
// Create a backup copy of the map (used before saving)
bool saveBackup();
@@ -99,8 +65,12 @@ private:
bool loadFile(std::istream& mapStream, const MapFormat& format,
const RootNodePtr& root, const std::string& filename);
- // Returns a (hopefully) unique file extension for saving
- static std::string getTemporaryFileExtension();
+ void loadInfoFile(const RootNodePtr& root, const std::string& filename, const NodeIndexMap& nodeMap);
+ void loadInfoFileFromStream(std::istream& infoFileStream, const RootNodePtr& root, const NodeIndexMap& nodeMap);
+
+ // Opens a stream for the given path, which might be VFS path or an absolute one. The streamProcessor
+ // function is then called with the opened stream. Throws std::runtime_error on stream open failure.
+ void openFileStream(const std::string& path, const std::function<void(std::istream&)>& streamProcessor);
static bool checkIsWriteable(const boost::filesystem::path& path);
};
diff --git a/radiant/map/MapResourceManager.cpp b/radiant/map/MapResourceManager.cpp
index 6acd65a..77c2f40 100644
--- a/radiant/map/MapResourceManager.cpp
+++ b/radiant/map/MapResourceManager.cpp
@@ -10,15 +10,10 @@
namespace map
{
-IMapResourcePtr MapResourceManager::capture(const std::string& path)
+IMapResourcePtr MapResourceManager::loadFromPath(const std::string& path)
{
// Create a new MapResource and return it.
- MapResourcePtr newResource(new map::MapResource(path));
-
- // Realise the new resource
- newResource->realise();
-
- return newResource;
+ return std::make_shared<MapResource>(path);
}
// RegisterableModule implementation
diff --git a/radiant/map/MapResourceManager.h b/radiant/map/MapResourceManager.h
index bda8fd5..d35caa1 100644
--- a/radiant/map/MapResourceManager.h
+++ b/radiant/map/MapResourceManager.h
@@ -10,13 +10,12 @@ class MapResourceManager :
public IMapResourceManager
{
public:
- // Capture a named resource.
- IMapResourcePtr capture(const std::string& path);
+ IMapResourcePtr loadFromPath(const std::string& path) override;
// RegisterableModule implementation
- virtual const std::string& getName() const;
- virtual const StringSet& getDependencies() const;
- virtual void initialiseModule(const ApplicationContext& ctx);
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
};
}
diff --git a/radiant/map/PointFile.cpp b/radiant/map/PointFile.cpp
index d52b4fb..3d44714 100644
--- a/radiant/map/PointFile.cpp
+++ b/radiant/map/PointFile.cpp
@@ -31,6 +31,8 @@ PointFile::PointFile() :
{
_renderstate = GlobalRenderSystem().capture("$POINTFILE");
GlobalRenderSystem().attachRenderable(*this);
+
+ GlobalMap().signal_mapEvent().connect(sigc::mem_fun(*this, &PointFile::onMapEvent));
}
void PointFile::destroy() {
@@ -38,6 +40,14 @@ void PointFile::destroy() {
_renderstate = ShaderPtr();
}
+void PointFile::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloading)
+ {
+ clear();
+ }
+}
+
// Static accessor method
PointFile& PointFile::Instance() {
static PointFile _instance;
diff --git a/radiant/map/PointFile.h b/radiant/map/PointFile.h
index 6ff076c..77b008a 100644
--- a/radiant/map/PointFile.h
+++ b/radiant/map/PointFile.h
@@ -1,13 +1,14 @@
-#ifndef POINTFILE_H_
-#define POINTFILE_H_
+#pragma once
#include <vector>
#include "irender.h"
+#include "imap.h"
#include "icommandsystem.h"
#include "irenderable.h"
#include "math/Vector3.h"
-namespace map {
+namespace map
+{
class PointFile :
public Renderable,
@@ -58,19 +59,19 @@ public:
/*
* Solid renderable submission function (front-end)
*/
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
/*
* Wireframe renderable submission function (front-end).
*/
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
- void setRenderSystem(const RenderSystemPtr& renderSystem)
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override
{}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight;
}
/** greebo: This sets the camera position to the next/prev leak spot.
@@ -99,8 +100,8 @@ private:
// Generates the OpenGL displaylist from the point vector
void generateDisplayList();
+
+ void onMapEvent(IMap::MapEvent ev);
};
} // namespace map
-
-#endif /*POINTFILE_H_*/
diff --git a/radiant/map/RegionManager.cpp b/radiant/map/RegionManager.cpp
index c7b9cfd..e719b1e 100644
--- a/radiant/map/RegionManager.cpp
+++ b/radiant/map/RegionManager.cpp
@@ -27,62 +27,31 @@
#include "selection/algorithm/Primitives.h"
#include "selection/algorithm/General.h"
#include "map/MapResource.h"
+#include "map/Map.h"
+#include "modulesystem/StaticModule.h"
#include <memory>
-namespace map {
+namespace map
+{
- namespace {
+ namespace
+ {
typedef std::shared_ptr<RegionManager> RegionManagerPtr;
const std::string GKEY_PLAYER_START_ECLASS = "/mapFormat/playerStartPoint";
-
- class AABBCollectorVisible :
- public scene::NodeVisitor
- {
- AABB& _targetAABB;
- public:
- AABBCollectorVisible(AABB& targetAABB) :
- _targetAABB(targetAABB)
- {}
-
- bool pre(const scene::INodePtr& node)
- {
- if (node->visible())
- {
- _targetAABB.includeAABB(node->worldAABB());
- }
-
- return true;
- }
- };
-
- AABB getVisibleBounds()
- {
- AABB returnValue;
- AABBCollectorVisible collector(returnValue);
-
- GlobalSceneGraph().root()->traverse(collector);
-
- return returnValue;
- }
}
RegionManager::RegionManager() :
_active(false)
-{
- _worldMin = game::current::getValue<float>("/defaults/minWorldCoord");
- _worldMax = game::current::getValue<float>("/defaults/maxWorldCoord");
-
- for (int i = 0; i < 6; i++) {
- _brushes[i] = scene::INodePtr();
- }
-}
+{}
-bool RegionManager::isEnabled() const {
+bool RegionManager::isEnabled() const
+{
return _active;
}
-void RegionManager::disable() {
+void RegionManager::disable()
+{
_active = false;
_bounds = AABB::createFromMinMax(Vector3(1,1,1)*_worldMin, Vector3(1,1,1)*_worldMax);
@@ -162,6 +131,7 @@ void RegionManager::addRegionBrushes()
for (int i = 0; i < 6; i++) {
// Create a new brush
_brushes[i] = GlobalBrushCreator().createBrush();
+
// Insert it into worldspawn
scene::addNodeToContainer(_brushes[i], GlobalMap().findOrInsertWorldspawn());
}
@@ -250,7 +220,7 @@ void RegionManager::removeRegionBrushes() {
for (int i = 0; i < 6; i++) {
// Remove the brushes from the scene
if (_brushes[i] != NULL) {
- GlobalMap().getWorldspawn()->removeChildNode(_brushes[i]);
+ GlobalMap().findOrInsertWorldspawn()->removeChildNode(_brushes[i]);
_brushes[i] = scene::INodePtr();
}
}
@@ -264,7 +234,7 @@ void RegionManager::removeRegionBrushes() {
// Static members (used as command targets for EventManager)
void RegionManager::disableRegion(const cmd::ArgumentList& args) {
- GlobalRegion().disable();
+ disable();
SceneChangeNotify();
}
@@ -284,12 +254,12 @@ void RegionManager::setRegionXY(const cmd::ArgumentList& args) {
);
// Set the bounds from the calculated XY rectangle
- GlobalRegion().setRegionFromXY(topLeft, lowerRight);
+ setRegionFromXY(topLeft, lowerRight);
}
else {
wxutil::Messagebox::ShowError(
_("Could not set Region: XY Top View not found."));
- GlobalRegion().disable();
+ disable();
}
SceneChangeNotify();
}
@@ -303,7 +273,7 @@ void RegionManager::setRegionFromBrush(const cmd::ArgumentList& args) {
const scene::INodePtr& node = GlobalSelectionSystem().ultimateSelected();
// Set the bounds of the region to the selection's extents
- GlobalRegion().setRegion(node->worldAABB());
+ setRegion(node->worldAABB());
// Delete the currently selected brush (undoable command)
{
@@ -316,7 +286,7 @@ void RegionManager::setRegionFromBrush(const cmd::ArgumentList& args) {
else {
wxutil::Messagebox::ShowError(
_("Could not set Region: please select a single Brush."));
- GlobalRegion().disable();
+ disable();
}
}
@@ -331,7 +301,7 @@ void RegionManager::setRegionFromSelection(const cmd::ArgumentList& args) {
AABB regionBounds = GlobalSelectionSystem().getWorkZone().bounds;
// Set the region
- GlobalRegion().setRegion(regionBounds);
+ setRegion(regionBounds);
// De-select all the selected items
GlobalSelectionSystem().setSelectedAll(false);
@@ -341,13 +311,13 @@ void RegionManager::setRegionFromSelection(const cmd::ArgumentList& args) {
}
else {
wxutil::Messagebox::ShowError(_("This command is not available in component mode."));
- GlobalRegion().disable();
+ disable();
}
}
else {
wxutil::Messagebox::ShowError(
_("Could not set Region: nothing selected."));
- GlobalRegion().disable();
+ disable();
}
}
@@ -370,16 +340,16 @@ void RegionManager::saveRegion(const cmd::ArgumentList& args)
// Filename is ok, start preparation
// Save the old region
- AABB oldRegionAABB = GlobalRegion().getRegion();
+ AABB oldRegionAABB = getRegion();
// Now check for the effective bounds so that all visible items are included
AABB visibleBounds = getVisibleBounds();
// Set the region bounds, but don't traverse the graph!
- GlobalRegion().setRegion(visibleBounds, false);
+ setRegion(visibleBounds, false);
// Add the region brushes
- GlobalRegion().addRegionBrushes();
+ addRegionBrushes();
if (!fileInfo.mapFormat)
{
@@ -394,10 +364,10 @@ void RegionManager::saveRegion(const cmd::ArgumentList& args)
fileInfo.fullPath);
// Remove the region brushes
- GlobalRegion().removeRegionBrushes();
+ removeRegionBrushes();
// Set the region AABB back to the state before saving
- GlobalRegion().setRegion(oldRegionAABB, false);
+ setRegion(oldRegionAABB, false);
// Add the filename to the recently used map list
GlobalMRU().insert(fileInfo.fullPath);
@@ -406,11 +376,11 @@ void RegionManager::saveRegion(const cmd::ArgumentList& args)
void RegionManager::initialiseCommands()
{
- GlobalCommandSystem().addCommand("SaveRegion", saveRegion);
- GlobalCommandSystem().addCommand("RegionOff", disableRegion);
- GlobalCommandSystem().addCommand("RegionSetXY", setRegionXY);
- GlobalCommandSystem().addCommand("RegionSetBrush", setRegionFromBrush);
- GlobalCommandSystem().addCommand("RegionSetSelection", setRegionFromSelection);
+ GlobalCommandSystem().addCommand("SaveRegion", std::bind(&RegionManager::saveRegion, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("RegionOff", std::bind(&RegionManager::disableRegion, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("RegionSetXY", std::bind(&RegionManager::setRegionXY, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("RegionSetBrush", std::bind(&RegionManager::setRegionFromBrush, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("RegionSetSelection", std::bind(&RegionManager::setRegionFromSelection, this, std::placeholders::_1));
GlobalEventManager().addCommand("SaveRegion", "SaveRegion");
GlobalEventManager().addCommand("RegionOff", "RegionOff");
@@ -419,14 +389,79 @@ void RegionManager::initialiseCommands()
GlobalEventManager().addCommand("RegionSetSelection", "RegionSetSelection");
}
-} // namespace map
+const std::string& RegionManager::getName() const
+{
+ static std::string _name("RegionManager");
+ return _name;
+}
-map::RegionManager& GlobalRegion() {
- static map::RegionManagerPtr _regionManager;
+const StringSet& RegionManager::getDependencies() const
+{
+ static StringSet _dependencies;
- if (_regionManager == NULL) {
- _regionManager = map::RegionManagerPtr(new map::RegionManager);
- }
+ if (_dependencies.empty())
+ {
+ _dependencies.insert(MODULE_MAP);
+ }
+
+ return _dependencies;
+}
+
+void RegionManager::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
+
+ initialiseCommands();
+
+ _worldMin = game::current::getValue<float>("/defaults/minWorldCoord");
+ _worldMax = game::current::getValue<float>("/defaults/maxWorldCoord");
+
+ for (int i = 0; i < 6; i++)
+ {
+ _brushes[i].reset();
+ }
+
+ GlobalMap().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &RegionManager::onMapEvent));
+}
+
+void RegionManager::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloading)
+ {
+ // Turn regioning off when unloading the map
+ disable();
+ clear();
+ }
+ else if (ev == IMap::MapLoaded)
+ {
+ // Disable when a new map has been loaded
+ disable();
+ }
+}
+
+AABB RegionManager::getVisibleBounds()
+{
+ AABB returnValue;
+
+ GlobalSceneGraph().root()->foreachNode([&](const scene::INodePtr& node)
+ {
+ if (node->visible())
+ {
+ returnValue.includeAABB(node->worldAABB());
+ }
- return *_regionManager;
+ return true;
+ });
+
+ return returnValue;
+}
+
+module::StaticModule<RegionManager> staticRegionManagerModule;
+
+} // namespace map
+
+map::RegionManager& GlobalRegion()
+{
+ return *map::staticRegionManagerModule.getModule();
}
diff --git a/radiant/map/RegionManager.h b/radiant/map/RegionManager.h
index e4c5f68..0743865 100644
--- a/radiant/map/RegionManager.h
+++ b/radiant/map/RegionManager.h
@@ -1,28 +1,32 @@
#pragma once
#include <list>
+#include "imodule.h"
#include "icommandsystem.h"
#include "math/AABB.h"
#include "math/Vector2.h"
#include "iscenegraph.h"
#include "ientity.h"
+#include "imap.h"
-/** greebo: The RegionManager provides methods to enable/disable
- * the regioning when map editing as well as functions
- * to set the region bounds from brushes/xyview/current selection.
+/**
+ * greebo: The RegionManager provides methods to enable/disable
+ * the regioning for map editing as well as functions
+ * to set the region bounds from brushes/xyview/current selection.
*
* Regioned nodes are hidden during map editing (they get their excluded bit set).
* It's still possible to apply additional filtering to a region via show/hide,
* these systems are independent of each other.
*
* @SaveRegion: This saves the current region (all non-excluded nodes) to a
- * specified file and places six wall/floor/ceiling brushes to
- * the file together with an info_player_start entity.
- * The info_player_start is placed at the current camera position.
+ * specified file and places six wall/floor/ceiling brushes to
+ * the file together with an info_player_start entity.
+ * The info_player_start is placed at the current camera position.
*/
namespace map {
-class RegionManager
+class RegionManager :
+ public RegisterableModule
{
// TRUE, if regioning is active
bool _active;
@@ -86,60 +90,67 @@ public:
*/
void setRegionFromXY(Vector2 topLeft, Vector2 lowerRight);
+ // RegisterableModule
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
+
+private:
/** greebo: Adds the bounding brushes that enclose the current region.
- */
+ */
void addRegionBrushes();
/** greebo: Removes the bounding brushes added by addRegionBrushes().
- */
+ */
void removeRegionBrushes();
/** greebo: The traversal function that is used to save the map to a file.
- * This ensures that only regioned items are saved.
- *
- * Note: the map saver passes its own walker to this function and leaves it up to it
- * whether the walker.pre() and walker.post() methods are invoked. This allows
- * filtering of the non-regioned nodes.
- */
+ * This ensures that only regioned items are saved.
+ *
+ * Note: the map saver passes its own walker to this function and leaves it up to it
+ * whether the walker.pre() and walker.post() methods are invoked. This allows
+ * filtering of the non-regioned nodes.
+ */
static void traverseRegion(const scene::INodePtr& root, scene::NodeVisitor& walker);
- // Static command targets for use in EventManager
-
/** greebo: Saves the current selection as Region to the queried file.
- */
- static void saveRegion(const cmd::ArgumentList& args);
+ */
+ void saveRegion(const cmd::ArgumentList& args);
/** greebo: Disables regioning and resets the bounds.
- */
- static void disableRegion(const cmd::ArgumentList& args);
+ */
+ void disableRegion(const cmd::ArgumentList& args);
/** greebo: Sets the region according to the XY bounds of the current orthoview
- */
- static void setRegionXY(const cmd::ArgumentList& args);
+ */
+ void setRegionXY(const cmd::ArgumentList& args);
/** greebo: Sets the region to the bounds of the currently drawn brush,
- * similar to the partial tall selection method.
- * A single brush has to be selected (an errormsg is displayed otherwise).
- *
- * Note: The brush is deleted after "use".
- */
- static void setRegionFromBrush(const cmd::ArgumentList& args);
+ * similar to the partial tall selection method.
+ * A single brush has to be selected (an errormsg is displayed otherwise).
+ *
+ * Note: The brush is deleted after "use".
+ */
+ void setRegionFromBrush(const cmd::ArgumentList& args);
/** greebo: Retrieves the AABB from the current selection and
- * takes it as new region bounds. The selection is NOT deleted.
- * Not available in component selection mode.
- * The selected items are de-selected after "use".
- */
- static void setRegionFromSelection(const cmd::ArgumentList& args);
+ * takes it as new region bounds. The selection is NOT deleted.
+ * Not available in component selection mode.
+ * The selected items are de-selected after "use".
+ */
+ void setRegionFromSelection(const cmd::ArgumentList& args);
/** greebo: Adds the region commands to the EventManager.
- */
- static void initialiseCommands();
+ */
+ void initialiseCommands();
+
+ void onMapEvent(IMap::MapEvent ev);
-private:
// Helper to create the actual brushes bounding the region
static void constructRegionBrushes(scene::INodePtr brushes[6],
const Vector3& region_mins, const Vector3& region_maxs);
+
+ AABB getVisibleBounds();
};
} // namespace map
diff --git a/radiant/map/RenderableAasFile.cpp b/radiant/map/RenderableAasFile.cpp
new file mode 100644
index 0000000..ff61ce7
--- /dev/null
+++ b/radiant/map/RenderableAasFile.cpp
@@ -0,0 +1,121 @@
+#include "RenderableAasFile.h"
+
+#include "iregistry.h"
+#include "imainframe.h"
+
+#include "registry/registry.h"
+
+namespace map
+{
+
+RenderableAasFile::RenderableAasFile() :
+ _renderNumbers(registry::getValue<bool>(RKEY_SHOW_AAS_AREA_NUMBERS)),
+ _hideDistantAreas(registry::getValue<bool>(RKEY_HIDE_DISTANT_AAS_AREAS)),
+ _hideDistanceSquared(registry::getValue<float>(RKEY_AAS_AREA_HIDE_DISTANCE))
+{
+ _hideDistanceSquared *= _hideDistanceSquared;
+
+ GlobalRegistry().signalForKey(RKEY_SHOW_AAS_AREA_NUMBERS).connect([this]()
+ {
+ _renderNumbers = registry::getValue<bool>(RKEY_SHOW_AAS_AREA_NUMBERS);
+ GlobalMainFrame().updateAllWindows();
+ });
+
+ GlobalRegistry().signalForKey(RKEY_HIDE_DISTANT_AAS_AREAS).connect([this]()
+ {
+ _hideDistantAreas = registry::getValue<bool>(RKEY_HIDE_DISTANT_AAS_AREAS);
+ _hideDistanceSquared = registry::getValue<float>(RKEY_AAS_AREA_HIDE_DISTANCE);
+ _hideDistanceSquared *= _hideDistanceSquared;
+ GlobalMainFrame().updateAllWindows();
+ });
+}
+
+void RenderableAasFile::setRenderSystem(const RenderSystemPtr& renderSystem)
+{
+ _renderSystem = renderSystem;
+}
+
+void RenderableAasFile::renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
+{
+ if (!_aasFile) return;
+
+ collector.SetState(_normalShader, RenderableCollector::eFullMaterials);
+
+ // Get the camera position for distance clipping
+ Matrix4 invModelView = volume.GetModelview().getFullInverse();
+ Vector3 viewPos = invModelView.t().getProjected();
+
+ for (const RenderableSolidAABB& aabb : _renderableAabbs)
+ {
+ if (_hideDistantAreas && (aabb.getAABB().getOrigin() - viewPos).getLengthSquared() > _hideDistanceSquared)
+ {
+ continue;
+ }
+
+ collector.addRenderable(aabb, Matrix4::getIdentity());
+ }
+
+ if (_renderNumbers)
+ {
+ collector.addRenderable(*this, Matrix4::getIdentity());
+ }
+}
+
+void RenderableAasFile::renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
+{
+ // Do nothing in wireframe mode
+ //renderSolid(collector, volume);
+}
+
+std::size_t RenderableAasFile::getHighlightFlags()
+{
+ return Highlight::NoHighlight;
+}
+
+void RenderableAasFile::setAasFile(const IAasFilePtr& aasFile)
+{
+ _aasFile = aasFile;
+
+ prepare();
+}
+
+void RenderableAasFile::render(const RenderInfo& info) const
+{
+ // draw label
+ // Render the area numbers
+ for (std::size_t areaNum = 0; areaNum < _aasFile->getNumAreas(); ++areaNum)
+ {
+ const IAasFile::Area& area = _aasFile->getArea(areaNum);
+
+ if (_hideDistantAreas && (area.center - info.getViewerLocation()).getLengthSquared() > _hideDistanceSquared)
+ {
+ continue;
+ }
+
+ glRasterPos3dv(area.center);
+ GlobalOpenGL().drawString(string::to_string(areaNum));
+ }
+}
+
+void RenderableAasFile::prepare()
+{
+ if (!_aasFile) return;
+
+ _normalShader = GlobalRenderSystem().capture("$AAS_AREA");
+
+ constructRenderables();
+}
+
+void RenderableAasFile::constructRenderables()
+{
+ _renderableAabbs.clear();
+
+ for (std::size_t areaNum = 0; areaNum < _aasFile->getNumAreas(); ++areaNum)
+ {
+ const IAasFile::Area& area = _aasFile->getArea(areaNum);
+
+ _renderableAabbs.push_back(RenderableSolidAABB(area.bounds));
+ }
+}
+
+} // namespace
diff --git a/radiant/map/RenderableAasFile.h b/radiant/map/RenderableAasFile.h
new file mode 100644
index 0000000..5f86c2c
--- /dev/null
+++ b/radiant/map/RenderableAasFile.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <list>
+#include <sigc++/trackable.h>
+
+#include "irenderable.h"
+#include "irender.h"
+#include "iaasfile.h"
+
+#include "entitylib.h"
+
+namespace map
+{
+
+const char* const RKEY_SHOW_AAS_AREA_NUMBERS = "user/ui/aasViewer/showNumbers";
+const char* const RKEY_HIDE_DISTANT_AAS_AREAS = "user/ui/aasViewer/hideDistantAreas";
+const char* const RKEY_AAS_AREA_HIDE_DISTANCE = "user/ui/aasViewer/hideDistance";
+
+// Renderable drawing all the area bounds of the attached AAS file,
+// optionally showing the area numbers too
+class RenderableAasFile :
+ public Renderable,
+ public OpenGLRenderable,
+ public sigc::trackable
+{
+private:
+ RenderSystemPtr _renderSystem;
+
+ IAasFilePtr _aasFile;
+
+ ShaderPtr _normalShader;
+
+ std::list<RenderableSolidAABB> _renderableAabbs;
+
+ bool _renderNumbers;
+ bool _hideDistantAreas;
+ float _hideDistanceSquared;
+
+public:
+ RenderableAasFile();
+
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ std::size_t getHighlightFlags() override;
+
+ void setAasFile(const IAasFilePtr& aasFile);
+
+ void render(const RenderInfo& info) const override;
+
+private:
+ void prepare();
+ void constructRenderables();
+};
+
+} // namespace
diff --git a/radiant/map/RootNode.h b/radiant/map/RootNode.h
index 8d2fd01..0d5828f 100644
--- a/radiant/map/RootNode.h
+++ b/radiant/map/RootNode.h
@@ -47,15 +47,15 @@ public:
ITargetManager& getTargetManager() override;
// Renderable implementation (empty)
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override
{}
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override
{}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
std::string name() const;
diff --git a/radiant/map/algorithm/AssignLayerMappingWalker.h b/radiant/map/algorithm/AssignLayerMappingWalker.h
deleted file mode 100644
index 77a7f23..0000000
--- a/radiant/map/algorithm/AssignLayerMappingWalker.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-#include "imodel.h"
-#include "iparticlenode.h"
-
-#include "../InfoFile.h"
-
-namespace map
-{
-
-class AssignLayerMappingWalker :
- public scene::NodeVisitor
-{
-private:
- InfoFile& _infoFile;
-
-public:
- AssignLayerMappingWalker(InfoFile& infoFile) :
- _infoFile(infoFile)
- {}
-
- virtual ~AssignLayerMappingWalker() {}
-
- bool pre(const scene::INodePtr& node)
- {
- // To prevent all the support node types from getting layers assigned
- // filter them out, only Entities and Primitives get mapped in the info file
- if (Node_isEntity(node) || Node_isPrimitive(node))
- {
- // Retrieve the next set of layer mappings and assign them
- node->assignToLayers(_infoFile.getNextLayerMapping());
- return true;
- }
-
- // All other node types inherit the layers from their parent node
- // Model / particle / target line
- scene::INodePtr parent = node->getParent();
-
- if (parent)
- {
- node->assignToLayers(parent->getLayers());
- }
-
- return true;
- }
-};
-
-} // namespace
diff --git a/radiant/map/algorithm/ChildPrimitives.cpp b/radiant/map/algorithm/ChildPrimitives.cpp
index 6ec9e98..b6e4fcb 100644
--- a/radiant/map/algorithm/ChildPrimitives.cpp
+++ b/radiant/map/algorithm/ChildPrimitives.cpp
@@ -26,7 +26,7 @@ public:
scene::GroupNodePtr groupNode = Node_getGroupNode(node);
// Don't handle the worldspawn children, they're safe&sound
- if (groupNode != NULL && entity->getKeyValue("classname") != "worldspawn")
+ if (groupNode != NULL && !entity->isWorldspawn())
{
groupNode->addOriginToChildren();
// Don't traverse the children
@@ -53,7 +53,7 @@ public:
scene::GroupNodePtr groupNode = Node_getGroupNode(node);
// Don't handle the worldspawn children, they're safe&sound
- if (groupNode != NULL && entity->getKeyValue("classname") != "worldspawn")
+ if (groupNode != NULL && !entity->isWorldspawn())
{
groupNode->removeOriginFromChildren();
// Don't traverse the children
diff --git a/radiant/map/algorithm/Clone.h b/radiant/map/algorithm/Clone.h
index db2d3cb..dbb5bd6 100644
--- a/radiant/map/algorithm/Clone.h
+++ b/radiant/map/algorithm/Clone.h
@@ -71,6 +71,11 @@ inline scene::INodePtr Node_Clone(const scene::INodePtr& node)
CloneAll visitor(clone);
node->traverseChildren(visitor);
+ // Cloned child nodes are assigned the layers of the source nodes
+ // update the layer visibility flags to make the layers assignemnt take effect
+ scene::UpdateNodeVisibilityWalker visibilityUpdater;
+ clone->traverse(visibilityUpdater);
+
return clone;
}
diff --git a/radiant/map/algorithm/InfoFileExporter.cpp b/radiant/map/algorithm/InfoFileExporter.cpp
deleted file mode 100644
index 826dec5..0000000
--- a/radiant/map/algorithm/InfoFileExporter.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-#include "InfoFileExporter.h"
-
-#include "imodel.h"
-#include "iselectionset.h"
-#include "iparticlenode.h"
-#include "itextstream.h"
-#include "../InfoFile.h"
-#include "debugging/ScenegraphUtils.h"
-
-#include <boost/algorithm/string/replace.hpp>
-
-namespace map
-{
-
-InfoFileExporter::InfoFileExporter(std::ostream& stream) :
- _stream(stream),
- _layerInfoCount(0)
-{
- // Write the information file header
- _stream << InfoFile::HEADER_SEQUENCE << " " << InfoFile::MAP_INFO_VERSION << std::endl;
- _stream << "{" << std::endl;
-
- // Export the names of the layers
- writeLayerNames();
- assembleSelectionSetInfo();
-
- // Write the NodeToLayerMapping header
- _stream << "\t" << InfoFile::NODE_TO_LAYER_MAPPING << std::endl;
- _stream << "\t{" << std::endl;
-}
-
-InfoFileExporter::~InfoFileExporter()
-{
- // Closing braces of NodeToLayerMapping block
- _stream << "\t}" << std::endl;
-
- rMessage() << _layerInfoCount << " node-to-layer mappings written." << std::endl;
-
- writeSelectionSetInfo();
-
- // Write the closing braces of the information file
- _stream << "}" << std::endl;
-}
-
-void InfoFileExporter::handleNode(const scene::INodePtr& node)
-{
- // Don't export the layer settings for models and particles, as they are not there
- // at map load/parse time - these shouldn't even be passed in here
- assert(node && !Node_isModel(node) && !particles::isParticleNode(node));
-
- // Open a Node block
- _stream << "\t\t" << InfoFile::NODE << " { ";
-
- scene::LayerList layers = node->getLayers();
-
- // Write a space-separated list of node IDs
- for (scene::LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i)
- {
- _stream << *i << " ";
- }
-
- // Close the Node block
- _stream << "}";
-
- // Write additional node info, for easier debugging of layer issues
- _stream << " // " << getNodeInfo(node);
-
- _stream << std::endl;
-
- _layerInfoCount++;
-}
-
-void InfoFileExporter::visitEntity(const scene::INodePtr& node, std::size_t entityNum)
-{
- handleNode(node);
-
- // Determine the item index for the selection set index mapping
- std::for_each(_selectionSetInfo.begin(), _selectionSetInfo.end(), [&] (SelectionSetExportInfo& info)
- {
- if (info.nodes.find(node) != info.nodes.end())
- {
- info.nodeIndices.insert(InfoFileExporter::SelectionSetExportInfo::IndexPair(entityNum, InfoFile::EMPTY_PRIMITVE_NUM));
- }
- });
-}
-
-void InfoFileExporter::visitPrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
-{
- handleNode(node);
-
- // Determine the item index for the selection set index mapping
- std::for_each(_selectionSetInfo.begin(), _selectionSetInfo.end(), [&] (SelectionSetExportInfo& info)
- {
- if (info.nodes.find(node) != info.nodes.end())
- {
- info.nodeIndices.insert(InfoFileExporter::SelectionSetExportInfo::IndexPair(entityNum, primitiveNum));
- }
- });
-}
-
-void InfoFileExporter::writeLayerNames()
-{
- // Open a "Layers" block
- _stream << "\t" << InfoFile::LAYERS << std::endl;
- _stream << "\t{" << std::endl;
-
- // Visit all layers and write them to the stream
- GlobalLayerSystem().foreachLayer([&](int layerId, const std::string& layerName)
- {
- _stream << "\t\t" << InfoFile::LAYER << " " << layerId << " { " << layerName << " }" << std::endl;
- });
-
- _stream << "\t}" << std::endl;
-}
-
-void InfoFileExporter::writeSelectionSetInfo()
-{
- // Selection Set output
- _stream << "\t" << InfoFile::SELECTION_SETS << std::endl;
-
- _stream << "\t{" << std::endl;
-
- std::size_t selectionSetCount = 0;
-
- std::for_each(_selectionSetInfo.begin(), _selectionSetInfo.end(), [&] (SelectionSetExportInfo& info)
- {
- std::string indices = "";
-
- std::for_each(info.nodeIndices.begin(), info.nodeIndices.end(),
- [&] (const InfoFileExporter::SelectionSetExportInfo::IndexPair& pair)
- {
- if (pair.second == InfoFile::EMPTY_PRIMITVE_NUM)
- {
- // only entity number
- indices += "( " + string::to_string(pair.first) + " ) ";
- }
- else
- {
- // entity & primitive number
- indices += "( " + string::to_string(pair.first) + " " + string::to_string(pair.second) + " ) ";
- }
- });
-
- // Make sure to escape the quotes of the set name, use the XML quote entity
- _stream << "\t\t" << InfoFile::SELECTION_SET << " " << selectionSetCount++
- << " { \"" << boost::algorithm::replace_all_copy(info.set->getName(), "\"", """) << "\" } "
- << " { " << indices << " } "
- << std::endl;
- });
-
- _stream << "\t}" << std::endl;
-
- rMessage() << _selectionSetInfo.size() << " selection sets exported." << std::endl;
-}
-
-void InfoFileExporter::assembleSelectionSetInfo()
-{
- // Visit all selection sets and assemble the info into the structures
- GlobalSelectionSetManager().foreachSelectionSet([&] (const selection::ISelectionSetPtr& set)
- {
- // Get all nodes of this selection set and store them for later use
- _selectionSetInfo.push_back(InfoFileExporter::SelectionSetExportInfo());
-
- _selectionSetInfo.back().set = set;
- _selectionSetInfo.back().nodes = set->getNodes();
- });
-}
-
-} // namespace
diff --git a/radiant/map/algorithm/InfoFileExporter.h b/radiant/map/algorithm/InfoFileExporter.h
deleted file mode 100644
index 5c9de33..0000000
--- a/radiant/map/algorithm/InfoFileExporter.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-
-#include <ostream>
-#include <sstream>
-#include "inode.h"
-#include "iselectionset.h"
-#include <map>
-
-namespace map
-{
-
-class InfoFileExporter
-{
-private:
- // The stream we're writing to
- std::ostream& _stream;
-
- // Number of node-to-layer mappings written
- std::size_t _layerInfoCount;
-
- struct SelectionSetExportInfo
- {
- // The set we're working with
- selection::ISelectionSetPtr set;
-
- // The nodes in this set
- std::set<scene::INodePtr> nodes;
-
- // The entity and primitive number pair
- typedef std::pair<std::size_t, std::size_t> IndexPair;
-
- // The node indices, which will be resolved during traversal
- std::set<IndexPair> nodeIndices;
- };
-
- // SelectionSet-related
- typedef std::vector<SelectionSetExportInfo> SelectionSetInfo;
- SelectionSetInfo _selectionSetInfo;
-
-public:
- // The constructor prepares the output stream
- InfoFileExporter(std::ostream& stream);
-
- // Cleans up the scene on destruction
- ~InfoFileExporter();
-
- // Is called by the owning MapExporter
- // Requirements: node must not be NULL and not a model/particle node.
- void visitEntity(const scene::INodePtr& node, std::size_t entityNum);
- void visitPrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum);
-
-private:
- // General handling of map nodes
- void handleNode(const scene::INodePtr& node);
-
- // Writes the names of the layers existing in this map
- void writeLayerNames();
-
- void writeSelectionSetInfo();
-
- // Get SelectionSet node mapping
- void assembleSelectionSetInfo();
-};
-typedef std::shared_ptr<InfoFileExporter> InfoFileExporterPtr;
-
-} // namespace
diff --git a/radiant/map/algorithm/MapExporter.h b/radiant/map/algorithm/MapExporter.h
index 1d347d5..1c49a92 100644
--- a/radiant/map/algorithm/MapExporter.h
+++ b/radiant/map/algorithm/MapExporter.h
@@ -5,7 +5,7 @@
#include "igame.h"
#include "wxutil/ModalProgressDialog.h"
-#include "InfoFileExporter.h"
+#include "../infofile/InfoFileExporter.h"
#include "EventRateLimiter.h"
namespace map
diff --git a/radiant/map/algorithm/MapImporter.cpp b/radiant/map/algorithm/MapImporter.cpp
index 808506b..30809c5 100644
--- a/radiant/map/algorithm/MapImporter.cpp
+++ b/radiant/map/algorithm/MapImporter.cpp
@@ -9,7 +9,6 @@
#include "registry/registry.h"
#include "string/string.h"
#include "wxutil/dialog/MessageBox.h"
-#include "../InfoFile.h"
namespace map
{
@@ -17,6 +16,7 @@ namespace map
namespace
{
const char* const RKEY_MAP_LOAD_STATUS_INTERLEAVE = "user/ui/map/loadStatusInterleave";
+ std::size_t EMPTY_PRIMITVE_NUM = std::numeric_limits<std::size_t>::max();
}
MapImporter::MapImporter(const scene::INodePtr& root, std::istream& inputStream) :
@@ -48,8 +48,8 @@ MapImporter::MapImporter(const scene::INodePtr& root, std::istream& inputStream)
bool MapImporter::addEntity(const scene::INodePtr& entityNode)
{
// Keep track of this entity
- _nodes.insert(NodeMap::value_type(
- NodeIndexPair(_entityCount, InfoFile::EMPTY_PRIMITVE_NUM), entityNode));
+ _nodes.insert(NodeIndexMap::value_type(
+ NodeIndexPair(_entityCount, EMPTY_PRIMITVE_NUM), entityNode));
_entityCount++;
@@ -74,7 +74,7 @@ bool MapImporter::addEntity(const scene::INodePtr& entityNode)
bool MapImporter::addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity)
{
- _nodes.insert(NodeMap::value_type(
+ _nodes.insert(NodeIndexMap::value_type(
NodeIndexPair(_entityCount, _primitiveCount), primitive));
_primitiveCount++;
@@ -98,11 +98,9 @@ bool MapImporter::addPrimitiveToEntity(const scene::INodePtr& primitive, const s
}
}
-scene::INodePtr MapImporter::getNodeByIndexPair(const NodeIndexPair& pair)
+const NodeIndexMap& MapImporter::getNodeMap() const
{
- NodeMap::const_iterator i = _nodes.find(pair);
-
- return i != _nodes.end() ? i->second : scene::INodePtr();
+ return _nodes;
}
double MapImporter::getProgressFraction()
diff --git a/radiant/map/algorithm/MapImporter.h b/radiant/map/algorithm/MapImporter.h
index 49362e9..a447382 100644
--- a/radiant/map/algorithm/MapImporter.h
+++ b/radiant/map/algorithm/MapImporter.h
@@ -2,6 +2,7 @@
#include "inode.h"
#include "imapformat.h"
+#include "imapinfofile.h"
#include <map>
#include "wxutil/ModalProgressDialog.h"
@@ -22,9 +23,6 @@ namespace map
class MapImporter :
public IMapImportFilter
{
-public:
- typedef std::pair<std::size_t, std::size_t> NodeIndexPair;
-
private:
scene::INodePtr _root;
@@ -45,9 +43,8 @@ private:
std::istream& _inputStream;
std::size_t _fileSize;
- // Keep track of all the entities and primitives for retrieval
- typedef std::map<NodeIndexPair, scene::INodePtr> NodeMap;
- NodeMap _nodes;
+ // Keep track of all the entities and primitives for later retrieval
+ NodeIndexMap _nodes;
public:
MapImporter(const scene::INodePtr& root, std::istream& inputStream);
@@ -55,8 +52,7 @@ public:
bool addEntity(const scene::INodePtr& entityNode);
bool addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity);
- // Get the entity or primitive by their number as they appear in the map file
- scene::INodePtr getNodeByIndexPair(const NodeIndexPair& pair);
+ const NodeIndexMap& getNodeMap() const;
private:
double getProgressFraction();
diff --git a/radiant/map/algorithm/Merge.h b/radiant/map/algorithm/Merge.h
index b099f8a..776e94c 100644
--- a/radiant/map/algorithm/Merge.h
+++ b/radiant/map/algorithm/Merge.h
@@ -62,10 +62,10 @@ public:
scene::INodePtr node = originalNode;
// greebo: Check if the visited node is the worldspawn of the other map
- if (node_is_worldspawn(node))
+ if (Node_isWorldspawn(node))
{
// Find the worldspawn of the target map
- scene::INodePtr world_node = GlobalMap().findWorldspawn();
+ const scene::INodePtr& world_node = GlobalMap().getWorldspawn();
if (world_node == NULL)
{
diff --git a/radiant/map/algorithm/WorldspawnArgFinder.h b/radiant/map/algorithm/WorldspawnArgFinder.h
index be2995d..2e62a5b 100644
--- a/radiant/map/algorithm/WorldspawnArgFinder.h
+++ b/radiant/map/algorithm/WorldspawnArgFinder.h
@@ -30,7 +30,7 @@ public:
if (ent != NULL) {
- if (ent->getKeyValue("classname") == "worldspawn") {
+ if (ent->isWorldspawn()) {
// Load the description spawnarg
_value = ent->getKeyValue(_key);
}
diff --git a/radiant/map/infofile/InfoFile.cpp b/radiant/map/infofile/InfoFile.cpp
new file mode 100644
index 0000000..6b9d300
--- /dev/null
+++ b/radiant/map/infofile/InfoFile.cpp
@@ -0,0 +1,143 @@
+#include "InfoFile.h"
+
+#include "itextstream.h"
+#include "imapinfofile.h"
+#include "string/convert.h"
+
+#include "i18n.h"
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace map
+{
+
+const char* const InfoFile::HEADER_SEQUENCE = "DarkRadiant Map Information File Version";
+
+// Pass the input stream to the constructor
+InfoFile::InfoFile(std::istream& infoStream, const scene::IMapRootNodePtr& root, const NodeIndexMap& nodeMap) :
+ _tok(infoStream),
+ _isValid(true),
+ _root(root),
+ _nodeMap(nodeMap)
+{}
+
+void InfoFile::parse()
+{
+ // Initialise the modules
+ GlobalMapInfoFileManager().foreachModule([](IMapInfoFileModule& module)
+ {
+ module.onInfoFileLoadStart();
+ });
+
+ // Parse the Header
+ parseInfoFileHeader();
+
+ // Parse the blocks
+ parseInfoFileBody();
+
+ // Apply the parsed info to the scene
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ module.applyInfoToScene(_root, _nodeMap);
+ });
+
+ // De-initialise the modules
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ module.onInfoFileLoadFinished();
+ });
+}
+
+void InfoFile::parseInfoFileHeader()
+{
+ try
+ {
+ std::vector<std::string> parts;
+ boost::algorithm::split(parts, HEADER_SEQUENCE, boost::algorithm::is_any_of(" "));
+
+ // Parse the string "DarkRadiant Map Information File Version"
+ for (std::size_t i = 0; i < parts.size(); i++)
+ {
+ _tok.assertNextToken(parts[i]);
+ }
+
+ float version = boost::lexical_cast<float>(_tok.nextToken());
+
+ if (version != MAP_INFO_VERSION)
+ {
+ _isValid = false;
+ throw parser::ParseException(_("Map Info File Version invalid"));
+ }
+ }
+ catch (parser::ParseException& e)
+ {
+ rError() << "[InfoFile] Unable to parse info file header: " << e.what() << std::endl;
+ _isValid = false;
+ return;
+ }
+ catch (boost::bad_lexical_cast& e)
+ {
+ rError() << "[InfoFile] Unable to parse info file version: " << e.what() << std::endl;
+ _isValid = false;
+ return;
+ }
+}
+
+void InfoFile::parseInfoFileBody()
+{
+ // The opening brace of the master block
+ _tok.assertNextToken("{");
+
+ while (_tok.hasMoreTokens())
+ {
+ std::string token = _tok.nextToken();
+
+ bool blockParsed = false;
+
+ // Send each block to the modules that are able to load it
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ if (!blockParsed && module.canParseBlock(token))
+ {
+ module.parseBlock(token, _tok);
+ blockParsed = true;
+ }
+ });
+
+ if (blockParsed)
+ {
+ continue; // block was processed by a module
+ }
+
+ if (token == "}")
+ {
+ break;
+ }
+
+ // Unknown token, try to ignore that block
+ rWarning() << "Unknown keyword " << token << " encountered, will try to ignore this block." << std::endl;
+
+ // We can only ignore a block if there is a block beginning curly brace
+ _tok.assertNextToken("{");
+
+ // Ignore the block
+ int depth = 1;
+
+ while (_tok.hasMoreTokens() && depth > 0)
+ {
+ std::string token2 = _tok.nextToken();
+
+ if (token2 == "{")
+ {
+ depth++;
+ }
+ else if (token2 == "}")
+ {
+ depth--;
+ }
+ }
+ }
+}
+
+} // namespace map
diff --git a/radiant/map/infofile/InfoFile.h b/radiant/map/infofile/InfoFile.h
new file mode 100644
index 0000000..7b59277
--- /dev/null
+++ b/radiant/map/infofile/InfoFile.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "imap.h"
+#include "imapinfofile.h"
+#include "parser/DefTokeniser.h"
+
+namespace map
+{
+
+class InfoFile
+{
+public:
+ // Tokens / Constants
+ // The version of the map info file
+ static const int MAP_INFO_VERSION = 2;
+
+ // InfoFile tokens --------------------------------------------------
+ static const char* const HEADER_SEQUENCE;
+
+private:
+ // The actual DefTokeniser to split the infoStream into pieces
+ parser::BasicDefTokeniser<std::istream> _tok;
+
+ // TRUE if the map info file was found to be valid
+ bool _isValid;
+
+ // Import root node
+ const scene::IMapRootNodePtr& _root;
+
+ // Index to Node mapping
+ const NodeIndexMap& _nodeMap;
+
+public:
+ // Pass the input stream to the constructor, plus some info about the map we're dealing with
+ InfoFile(std::istream& infoStream, const scene::IMapRootNodePtr& root, const NodeIndexMap& nodeMap);
+
+ // Parse the entire file
+ void parse();
+
+private:
+ void parseInfoFileHeader();
+ void parseInfoFileBody();
+};
+
+} // namespace map
diff --git a/radiant/map/infofile/InfoFileExporter.cpp b/radiant/map/infofile/InfoFileExporter.cpp
new file mode 100644
index 0000000..007a3c2
--- /dev/null
+++ b/radiant/map/infofile/InfoFileExporter.cpp
@@ -0,0 +1,62 @@
+#include "InfoFileExporter.h"
+
+#include "imapinfofile.h"
+#include "itextstream.h"
+#include "InfoFile.h"
+
+namespace map
+{
+
+InfoFileExporter::InfoFileExporter(std::ostream& stream) :
+ _stream(stream)
+{
+ GlobalMapInfoFileManager().foreachModule([](IMapInfoFileModule& module)
+ {
+ module.onInfoFileSaveStart();
+ });
+
+ // Write the information file header
+ _stream << InfoFile::HEADER_SEQUENCE << " " << InfoFile::MAP_INFO_VERSION << std::endl;
+ _stream << "{" << std::endl;
+}
+
+InfoFileExporter::~InfoFileExporter()
+{
+ // Tell the info file modules to write their data now
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ rMessage() << "Writing info file blocks for " << module.getName() << std::endl;
+
+ module.writeBlocks(_stream);
+ });
+
+ // Write the closing braces of the information file
+ _stream << "}" << std::endl;
+
+ _stream.flush();
+
+ GlobalMapInfoFileManager().foreachModule([](IMapInfoFileModule& module)
+ {
+ module.onInfoFileSaveFinished();
+ });
+}
+
+void InfoFileExporter::visitEntity(const scene::INodePtr& node, std::size_t entityNum)
+{
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ module.onSaveEntity(node, entityNum);
+ });
+}
+
+void InfoFileExporter::visitPrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
+{
+ GlobalMapInfoFileManager().foreachModule([&](IMapInfoFileModule& module)
+ {
+ module.onSavePrimitive(node, entityNum, primitiveNum);
+ });
+}
+
+
+
+} // namespace
diff --git a/radiant/map/infofile/InfoFileExporter.h b/radiant/map/infofile/InfoFileExporter.h
new file mode 100644
index 0000000..0d382dc
--- /dev/null
+++ b/radiant/map/infofile/InfoFileExporter.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <ostream>
+#include <sstream>
+#include "inode.h"
+#include <map>
+
+namespace map
+{
+
+class InfoFileExporter
+{
+private:
+ // The stream we're writing to
+ std::ostream& _stream;
+
+public:
+ // The constructor prepares the output stream
+ InfoFileExporter(std::ostream& stream);
+
+ // Cleans up the scene on destruction
+ ~InfoFileExporter();
+
+ // Is called by the owning MapExporter
+ // Requirements: node must not be NULL and not a model/particle node.
+ void visitEntity(const scene::INodePtr& node, std::size_t entityNum);
+ void visitPrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum);
+};
+typedef std::shared_ptr<InfoFileExporter> InfoFileExporterPtr;
+
+} // namespace
diff --git a/radiant/map/infofile/InfoFileManager.cpp b/radiant/map/infofile/InfoFileManager.cpp
new file mode 100644
index 0000000..877aa95
--- /dev/null
+++ b/radiant/map/infofile/InfoFileManager.cpp
@@ -0,0 +1,67 @@
+#include "InfoFileManager.h"
+
+#include "itextstream.h"
+#include "modulesystem/StaticModule.h"
+
+namespace map
+{
+
+void InfoFileManager::registerInfoFileModule(const IMapInfoFileModulePtr& module)
+{
+ if (_modules.find(module) != _modules.end())
+ {
+ rWarning() << "Duplicate info file module registered: " << module->getName() << std::endl;
+ return;
+ }
+
+ _modules.insert(module);
+}
+
+void InfoFileManager::unregisterInfoFileModule(const IMapInfoFileModulePtr& module)
+{
+ if (_modules.find(module) == _modules.end())
+ {
+ rWarning() << "Trying to unregister non-existent info file module: " << module->getName() << std::endl;
+ return;
+
+ }
+
+ _modules.erase(module);
+}
+
+void InfoFileManager::foreachModule(const std::function<void(IMapInfoFileModule&)>& functor)
+{
+ for (const IMapInfoFileModulePtr& module : _modules)
+ {
+ functor(*module);
+ }
+}
+
+const std::string& InfoFileManager::getName() const
+{
+ static std::string _name(MODULE_MAPINFOFILEMANAGER);
+ return _name;
+}
+
+const StringSet& InfoFileManager::getDependencies() const
+{
+ static StringSet _dependencies;
+ return _dependencies;
+}
+
+void InfoFileManager::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
+}
+
+void InfoFileManager::shutdownModule()
+{
+ rMessage() << getName() << "::shudownModule called." << std::endl;
+
+ _modules.clear();
+}
+
+// Define the static InfoFileManager module
+module::StaticModule<InfoFileManager> infoFileManagerModule;
+
+}
diff --git a/radiant/map/infofile/InfoFileManager.h b/radiant/map/infofile/InfoFileManager.h
new file mode 100644
index 0000000..8d8af86
--- /dev/null
+++ b/radiant/map/infofile/InfoFileManager.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <set>
+#include "imapinfofile.h"
+
+namespace map
+{
+
+class InfoFileManager :
+ public IMapInfoFileManager
+{
+private:
+ std::set<IMapInfoFileModulePtr> _modules;
+
+public:
+ void registerInfoFileModule(const IMapInfoFileModulePtr& module) override;
+ void unregisterInfoFileModule(const IMapInfoFileModulePtr& module) override;
+
+ void foreachModule(const std::function<void(IMapInfoFileModule&)>& functor) override;
+
+ // Module interface
+ const std::string& getName() const override;
+ const StringSet& getDependencies() const override;
+ void initialiseModule(const ApplicationContext& ctx) override;
+ void shutdownModule() override;
+};
+
+}
+
diff --git a/radiant/modulesystem/ModuleRegistry.cpp b/radiant/modulesystem/ModuleRegistry.cpp
index 97628f8..7efec10 100644
--- a/radiant/modulesystem/ModuleRegistry.cpp
+++ b/radiant/modulesystem/ModuleRegistry.cpp
@@ -158,11 +158,11 @@ void ModuleRegistry::initialiseModules()
// Make sure this isn't called again
_modulesInitialised = true;
- // Fire the signal now
- _sigAllModulesInitialised.emit();
-
_progress = 1.0f;
ui::Splash::Instance().setProgressAndText(_("Modules initialised"), _progress);
+
+ // Fire the signal now, this will destroy the Splash dialog as well
+ _sigAllModulesInitialised.emit();
}
void ModuleRegistry::shutdownModules()
diff --git a/radiant/patch/Patch.cpp b/radiant/patch/Patch.cpp
index e6093ed..32eac56 100644
--- a/radiant/patch/Patch.cpp
+++ b/radiant/patch/Patch.cpp
@@ -45,32 +45,29 @@ inline bool double_valid(double f) {
// ====== Patch Implementation =========================================================================
-// Initialise the cycle cap index member variable
-int Patch::m_CycleCapIndex = 0;
-
namespace {
const std::size_t MAX_PATCH_SUBDIVISIONS = 32;
}
// Constructor
-Patch::Patch(PatchNode& node, const Callback& evaluateTransform) :
+Patch::Patch(PatchNode& node) :
_node(node),
_shader(texdef_name_default()),
_undoStateSaver(NULL),
_solidRenderable(_mesh),
_wireframeRenderable(_mesh),
_fixedWireframeRenderable(_mesh),
- _renderableCtrlPoints(GL_POINTS, m_ctrl_vertices),
- _renderableLattice(GL_LINES, m_lattice_indices, m_ctrl_vertices),
- m_transformChanged(false),
- _tesselationChanged(true),
- m_evaluateTransform(evaluateTransform)
+ _renderableNTBVectors(_mesh),
+ _renderableCtrlPoints(GL_POINTS, _ctrl_vertices),
+ _renderableLattice(GL_LINES, _latticeIndices, _ctrl_vertices),
+ _transformChanged(false),
+ _tesselationChanged(true)
{
construct();
}
// Copy constructor (create this patch from another patch)
-Patch::Patch(const Patch& other, PatchNode& node, const Callback& evaluateTransform) :
+Patch::Patch(const Patch& other, PatchNode& node) :
IPatch(other),
Bounded(other),
Snappable(other),
@@ -81,33 +78,30 @@ Patch::Patch(const Patch& other, PatchNode& node, const Callback& evaluateTransf
_solidRenderable(_mesh),
_wireframeRenderable(_mesh),
_fixedWireframeRenderable(_mesh),
- _renderableCtrlPoints(GL_POINTS, m_ctrl_vertices),
- _renderableLattice(GL_LINES, m_lattice_indices, m_ctrl_vertices),
- m_transformChanged(false),
- _tesselationChanged(true),
- m_evaluateTransform(evaluateTransform)
+ _renderableNTBVectors(_mesh),
+ _renderableCtrlPoints(GL_POINTS, _ctrl_vertices),
+ _renderableLattice(GL_LINES, _latticeIndices, _ctrl_vertices),
+ _transformChanged(false),
+ _tesselationChanged(true)
{
// Initalise the default values
construct();
// Copy over the definitions from the <other> patch
- m_patchDef3 = other.m_patchDef3;
- m_subdivisions_x = other.m_subdivisions_x;
- m_subdivisions_y = other.m_subdivisions_y;
- setDims(other.m_width, other.m_height);
- copy_ctrl(m_ctrl.begin(), other.m_ctrl.begin(), other.m_ctrl.begin()+(m_width*m_height));
+ _patchDef3 = other._patchDef3;
+ _subDivisions = other._subDivisions;
+ setDims(other._width, other._height);
+ copy_ctrl(_ctrl.begin(), other._ctrl.begin(), other._ctrl.begin()+(_width*_height));
_shader.setMaterialName(other._shader.getMaterialName());
controlPointsChanged();
}
-// greebo: Initialises the patch member variables
-void Patch::construct() {
- m_bOverlay = false;
- m_width = m_height = 0;
+void Patch::construct()
+{
+ _width = _height = 0;
- m_patchDef3 = false;
- m_subdivisions_x = 0;
- m_subdivisions_y = 0;
+ _patchDef3 = false;
+ _subDivisions = Subdivisions(0, 0);
// Check, if the shader name is correct
check_shader();
@@ -115,29 +109,29 @@ void Patch::construct() {
// Get the current control point array
PatchControlArray& Patch::getControlPoints() {
- return m_ctrl;
+ return _ctrl;
}
// Same as above, just for const arguments
const PatchControlArray& Patch::getControlPoints() const {
- return m_ctrl;
+ return _ctrl;
}
// Get the (temporary) transformed control point array, not the saved ones
PatchControlArray& Patch::getControlPointsTransformed() {
- return m_ctrlTransformed;
+ return _ctrlTransformed;
}
const PatchControlArray& Patch::getControlPointsTransformed() const {
- return m_ctrlTransformed;
+ return _ctrlTransformed;
}
std::size_t Patch::getWidth() const {
- return m_width;
+ return _width;
}
std::size_t Patch::getHeight() const {
- return m_height;
+ return _height;
}
void Patch::setDims(std::size_t w, std::size_t h)
@@ -151,19 +145,20 @@ void Patch::setDims(std::size_t w, std::size_t h)
w = MIN_PATCH_WIDTH;
if((h%2)==0)
- m_height -= 1;
+ _height -= 1;
ASSERT_MESSAGE(h <= MAX_PATCH_HEIGHT, "patch too tall");
if(h > MAX_PATCH_HEIGHT)
h = MAX_PATCH_HEIGHT;
else if(h < MIN_PATCH_HEIGHT)
h = MIN_PATCH_HEIGHT;
- m_width = w; m_height = h;
+ _width = w;
+ _height = h;
- if(m_width * m_height != m_ctrl.size())
+ if(_width * _height != _ctrl.size())
{
- m_ctrl.resize(m_width * m_height);
- onAllocate(m_ctrl.size());
+ _ctrl.resize(_width * _height);
+ onAllocate(_ctrl.size());
}
}
@@ -196,8 +191,9 @@ void Patch::onAllocate(std::size_t size)
}
// Return the interally stored AABB
-const AABB& Patch::localAABB() const {
- return m_aabb_local;
+const AABB& Patch::localAABB() const
+{
+ return _localAABB;
}
// Render functions: solid mode
@@ -209,6 +205,10 @@ void Patch::render_solid(RenderableCollector& collector, const VolumeTest& volum
collector.SetState(_shader.getGLShader(), RenderableCollector::eFullMaterials);
collector.addRenderable(_solidRenderable, localToWorld, entity);
+
+#if DEBUG_PATCH_NTB_VECTORS
+ _renderableVectors.render(collector, volume, localToWorld);
+#endif
}
// Render functions for WireFrame rendering
@@ -219,7 +219,7 @@ void Patch::render_wireframe(RenderableCollector& collector, const VolumeTest& v
collector.SetState(_shader.getGLShader(), RenderableCollector::eFullMaterials);
- if (m_patchDef3) {
+ if (_patchDef3) {
collector.addRenderable(_fixedWireframeRenderable, localToWorld);
}
else {
@@ -254,6 +254,10 @@ void Patch::setRenderSystem(const RenderSystemPtr& renderSystem)
_renderSystem = renderSystem;
_shader.setRenderSystem(renderSystem);
+#if DEBUG_PATCH_NTB_VECTORS
+ _renderableNTBVectors.setRenderSystem(renderSystem);
+#endif
+
if (renderSystem)
{
_pointShader = renderSystem->capture("$POINT");
@@ -279,9 +283,9 @@ void Patch::testSelect(Selector& selector, SelectionTest& test)
SelectionIntersection best;
IndexPointer::index_type* pIndex = &_mesh.indices.front();
- for (std::size_t s=0; s<_mesh.m_numStrips; s++) {
- test.TestQuadStrip(vertexpointer_arbitrarymeshvertex(&_mesh.vertices.front()), IndexPointer(pIndex, _mesh.m_lenStrips), best);
- pIndex += _mesh.m_lenStrips;
+ for (std::size_t s=0; s<_mesh.numStrips; s++) {
+ test.TestQuadStrip(vertexpointer_arbitrarymeshvertex(&_mesh.vertices.front()), IndexPointer(pIndex, _mesh.lenStrips), best);
+ pIndex += _mesh.lenStrips;
}
if (best.valid()) {
@@ -293,8 +297,8 @@ void Patch::testSelect(Selector& selector, SelectionTest& test)
void Patch::transform(const Matrix4& matrix)
{
// Cycle through all the patch control vertices and transform the points
- for (PatchControlIter i = m_ctrlTransformed.begin();
- i != m_ctrlTransformed.end();
+ for (PatchControlIter i = _ctrlTransformed.begin();
+ i != _ctrlTransformed.end();
++i)
{
i->vertex = matrix.transformPoint(i->vertex);
@@ -303,7 +307,7 @@ void Patch::transform(const Matrix4& matrix)
// Check the handedness of the matrix and invert it if needed
if(matrix.getHandedness() == Matrix4::LEFTHANDED)
{
- PatchControlArray_invert(m_ctrlTransformed, m_width, m_height);
+ PatchControlArray_invert(_ctrlTransformed, _width, _height);
}
// Mark this patch as changed
@@ -313,7 +317,7 @@ void Patch::transform(const Matrix4& matrix)
// Called if the patch has changed, so that the dirty flags are set
void Patch::transformChanged()
{
- m_transformChanged = true;
+ _transformChanged = true;
_node.lightsChanged();
_tesselationChanged = true;
}
@@ -322,27 +326,27 @@ void Patch::transformChanged()
void Patch::evaluateTransform()
{
// Only do something, if the patch really has changed
- if (m_transformChanged)
+ if (_transformChanged)
{
- m_transformChanged = false;
+ _transformChanged = false;
revertTransform();
- m_evaluateTransform();
+ _node.evaluateTransform();
}
}
-// Revert the changes, fall back to the saved state in <m_ctrl>
+// Revert the changes, fall back to the saved state in <_ctrl>
void Patch::revertTransform()
{
- m_ctrlTransformed = m_ctrl;
+ _ctrlTransformed = _ctrl;
}
-// Apply the transformed control array, save it into <m_ctrl> and overwrite the old values
+// Apply the transformed control array, save it into <_ctrl> and overwrite the old values
void Patch::freezeTransform()
{
undoSave();
- // Save the transformed working set array over m_ctrl
- m_ctrl = m_ctrlTransformed;
+ // Save the transformed working set array over _ctrl
+ _ctrl = _ctrlTransformed;
// Don't call controlPointsChanged() here since that one will re-apply the
// current transformation matrix, possible the second time.
@@ -373,7 +377,7 @@ void Patch::snapto(float snap)
{
undoSave();
- for(PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+ for(PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i)
{
i->vertex.snap(snap);
}
@@ -428,12 +432,12 @@ int Patch::getShaderFlags() const
// Return a defined patch control vertex at <row>,<col>
PatchControl& Patch::ctrlAt(std::size_t row, std::size_t col) {
- return m_ctrl[row*m_width+col];
+ return _ctrl[row*_width+col];
}
// The same as above just for const
const PatchControl& Patch::ctrlAt(std::size_t row, std::size_t col) const {
- return m_ctrl[row*m_width+col];
+ return _ctrl[row*_width+col];
}
// called just before an action to save the undo state
@@ -449,7 +453,7 @@ void Patch::undoSave()
// Save the current patch state into a new UndoMemento instance (allocated on heap) and return it to the undo observer
IUndoMementoPtr Patch::exportState() const
{
- return IUndoMementoPtr(new SavedState(m_width, m_height, m_ctrl, m_patchDef3, m_subdivisions_x, m_subdivisions_y, _shader.getMaterialName()));
+ return IUndoMementoPtr(new SavedState(_width, _height, _ctrl, _patchDef3, _subDivisions.x(), _subDivisions.y(), _shader.getMaterialName()));
}
// Revert the state of this patch to the one that has been saved in the UndoMemento
@@ -463,13 +467,12 @@ void Patch::importState(const IUndoMementoPtr& state)
// copy construct
{
- m_width = other.m_width;
- m_height = other.m_height;
- m_ctrl = other.m_ctrl;
- onAllocate(m_ctrl.size());
- m_patchDef3 = other.m_patchDef3;
- m_subdivisions_x = other.m_subdivisions_x;
- m_subdivisions_y = other.m_subdivisions_y;
+ _width = other.m_width;
+ _height = other.m_height;
+ _ctrl = other.m_ctrl;
+ onAllocate(_ctrl.size());
+ _patchDef3 = other.m_patchDef3;
+ _subDivisions = Subdivisions(other.m_subdivisions_x, other.m_subdivisions_y);
_shader.setMaterialName(other._materialName);
}
@@ -496,9 +499,6 @@ Patch::~Patch()
(*i++)->onPatchDestruction();
}
- BezierCurveTreeArray_deleteAll(_mesh.curveTreeU);
- BezierCurveTreeArray_deleteAll(_mesh.curveTreeV);
-
// Release the shaders
_pointShader.reset();
_latticeShader.reset();
@@ -506,12 +506,12 @@ Patch::~Patch()
bool Patch::isValid() const
{
- if(!m_width || !m_height)
+ if(!_width || !_height)
{
return false;
}
- for(PatchControlConstIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+ for(PatchControlConstIter i = _ctrl.begin(); i != _ctrl.end(); ++i)
{
if(!double_valid((*i).vertex.x())
|| !double_valid((*i).vertex.y())
@@ -537,10 +537,10 @@ bool Patch::isDegenerate() const {
// Compare each control's 3D coordinates with the previous one and break out
// on the first non-equal one
- for (PatchControlConstIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlConstIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
// Skip the first comparison
- if (i != m_ctrl.begin() && !i->vertex.isEqual(prev, 0.0001)) {
+ if (i != _ctrl.begin() && !i->vertex.isEqual(prev, 0.0001)) {
return false;
}
@@ -559,49 +559,50 @@ void Patch::updateTesselation()
_tesselationChanged = false;
- m_ctrl_vertices.clear();
- m_lattice_indices.clear();
+ _ctrl_vertices.clear();
+ _latticeIndices.clear();
- if(!isValid())
+ if (!isValid())
{
_mesh.clear();
- m_aabb_local = AABB();
+ _localAABB = AABB();
return;
}
-
- BuildTesselationCurves(ROW);
- BuildTesselationCurves(COL);
- BuildVertexArray();
+
+ // Run the tesselation code
+ _mesh.generate(_width, _height, _ctrlTransformed, subdivisionsFixed(), getSubdivisions());
+
updateAABB();
-
+
+ // Generate the indices for the coloured control points and the lines in between
IndexBuffer ctrl_indices;
- m_lattice_indices.reserve(((m_width * (m_height - 1)) + (m_height * (m_width - 1))) << 1);
- ctrl_indices.reserve(m_ctrlTransformed.size());
+ _latticeIndices.reserve(((_width * (_height - 1)) + (_height * (_width - 1))) << 1);
+ ctrl_indices.reserve(_ctrlTransformed.size());
- UniqueVertexBuffer<VertexCb> inserter(m_ctrl_vertices);
- for(PatchControlIter i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
+ UniqueVertexBuffer<VertexCb> inserter(_ctrl_vertices);
+ for (PatchControlIter i = _ctrlTransformed.begin(); i != _ctrlTransformed.end(); ++i)
{
- ctrl_indices.push_back(inserter.insert(pointvertex_quantised(VertexCb(i->vertex, colour_for_index(i - m_ctrlTransformed.begin(), m_width)))));
+ ctrl_indices.push_back(inserter.insert(pointvertex_quantised(VertexCb(i->vertex, colour_for_index(i - _ctrlTransformed.begin(), _width)))));
}
for(IndexBuffer::iterator i = ctrl_indices.begin(); i != ctrl_indices.end(); ++i)
{
- if(std::size_t(i - ctrl_indices.begin()) % m_width)
+ if(std::size_t(i - ctrl_indices.begin()) % _width)
{
- m_lattice_indices.push_back(*(i - 1));
- m_lattice_indices.push_back(*i);
+ _latticeIndices.push_back(*(i - 1));
+ _latticeIndices.push_back(*i);
}
- if(std::size_t(i - ctrl_indices.begin()) >= m_width)
+ if(std::size_t(i - ctrl_indices.begin()) >= _width)
{
- m_lattice_indices.push_back(*(i - m_width));
- m_lattice_indices.push_back(*i);
+ _latticeIndices.push_back(*(i - _width));
+ _latticeIndices.push_back(*i);
}
}
_solidRenderable.queueUpdate();
- if (m_patchDef3)
+ if (_patchDef3)
{
_fixedWireframeRenderable.queueUpdate();
}
@@ -615,7 +616,7 @@ void Patch::InvertMatrix()
{
undoSave();
- PatchControlArray_invert(m_ctrl, m_width, m_height);
+ PatchControlArray_invert(_ctrl, _width, _height);
controlPointsChanged();
}
@@ -625,20 +626,20 @@ void Patch::TransposeMatrix()
undoSave();
// greebo: create a new temporary control array to hold the "old" matrix
- PatchControlArray tmp = m_ctrl;
+ PatchControlArray tmp = _ctrl;
std::size_t i = 0;
- for (std::size_t w = 0; w < m_width; ++w)
+ for (std::size_t w = 0; w < _width; ++w)
{
- for (std::size_t h = 0; h < m_height; ++h)
+ for (std::size_t h = 0; h < _height; ++h)
{
// Copy elements such that the columns end up as rows
- m_ctrl[i++] = tmp[h*m_width + w];
+ _ctrl[i++] = tmp[h*_width + w];
}
}
- std::swap(m_width, m_height);
+ std::swap(_width, _height);
controlPointsChanged();
}
@@ -653,15 +654,15 @@ void Patch::Redisperse(EMatrixMajor mt)
switch(mt)
{
case COL:
- width = (m_width-1)>>1;
- height = m_height;
+ width = (_width-1)>>1;
+ height = _height;
col_stride = 1;
- row_stride = m_width;
+ row_stride = _width;
break;
case ROW:
- width = (m_height-1)>>1;
- height = m_width;
- col_stride = m_width;
+ width = (_height-1)>>1;
+ height = _width;
+ col_stride = _width;
row_stride = 1;
break;
default:
@@ -671,7 +672,7 @@ void Patch::Redisperse(EMatrixMajor mt)
for(h=0;h<height;h++)
{
- p1 = m_ctrl.begin()+(h*row_stride);
+ p1 = _ctrl.begin()+(h*row_stride);
for(w=0;w<width;w++)
{
p2 = p1+col_stride;
@@ -692,22 +693,22 @@ void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst) {
// Decide whether we should insert rows or columns
if (bColumn) {
// The insert point is 1 for "beginning" and width-2 for "end"
- insertColumns(bFirst ? 1 : m_width-2);
+ insertColumns(bFirst ? 1 : _width-2);
}
else {
// The insert point is 1 for "beginning" and height-2 for "end"
- insertRows(bFirst ? 1 : m_height-2);
+ insertRows(bFirst ? 1 : _height-2);
}
}
else {
// Col/Row Removal
if (bColumn) {
// Column removal, pass TRUE
- removePoints(true, bFirst ? 2 : m_width - 3);
+ removePoints(true, bFirst ? 2 : _width - 3);
}
else {
// Row removal, pass FALSE
- removePoints(false, bFirst ? 2 : m_height - 3);
+ removePoints(false, bFirst ? 2 : _height - 3);
}
}
}
@@ -721,8 +722,8 @@ void Patch::InsertRemove(bool bInsert, bool bColumn, bool bFirst) {
void Patch::appendPoints(bool columns, bool beginning) {
bool rows = !columns; // Shortcut for readability
- if ((columns && m_width + 2 > MAX_PATCH_WIDTH) ||
- (rows && m_height + 2 > MAX_PATCH_HEIGHT))
+ if ((columns && _width + 2 > MAX_PATCH_WIDTH) ||
+ (rows && _height + 2 > MAX_PATCH_HEIGHT))
{
rError() << "Patch::appendPoints() error: " <<
"Cannot make patch any larger.\n";
@@ -733,9 +734,9 @@ void Patch::appendPoints(bool columns, bool beginning) {
undoSave();
// Create a backup of the old control vertices
- PatchControlArray oldCtrl = m_ctrl;
- std::size_t oldHeight = m_height;
- std::size_t oldWidth = m_width;
+ PatchControlArray oldCtrl = _ctrl;
+ std::size_t oldHeight = _height;
+ std::size_t oldWidth = _width;
// Resize this patch
setDims(columns ? oldWidth+2 : oldWidth, rows ? oldHeight+2 : oldHeight);
@@ -747,11 +748,11 @@ void Patch::appendPoints(bool columns, bool beginning) {
// We're copying the old patch matrix into a sub-matrix of the new patch
// Fill in the control vertex values into the target area using this loop
for (std::size_t newRow = targetRowStart, oldRow = 0;
- newRow < m_height && oldRow < oldHeight;
+ newRow < _height && oldRow < oldHeight;
newRow++, oldRow++)
{
for (std::size_t newCol = targetColStart, oldCol = 0;
- oldCol < oldWidth && newCol < m_width;
+ oldCol < oldWidth && newCol < _width;
oldCol++, newCol++)
{
// Copy the control vertex from the old patch to the new patch
@@ -764,15 +765,15 @@ void Patch::appendPoints(bool columns, bool beginning) {
// Extrapolate the vertex attributes of the columns
// These are the indices of the new columns
- std::size_t newCol1 = beginning ? 0 : m_width - 1; // The outermost column
- std::size_t newCol2 = beginning ? 1 : m_width - 2; // The nearest column
+ std::size_t newCol1 = beginning ? 0 : _width - 1; // The outermost column
+ std::size_t newCol2 = beginning ? 1 : _width - 2; // The nearest column
// This indicates the direction we are taking the base values from
// If we start at the beginning, we have to take the values on
// the "right", hence the +1 index
int neighbour = beginning ? +1 : -1;
- for (std::size_t row = 0; row < m_height; row++) {
+ for (std::size_t row = 0; row < _height; row++) {
// The distance of the two neighbouring columns,
// this is taken as extrapolation value
Vector3 vertexDiff = ctrlAt(row, newCol2 + neighbour).vertex -
@@ -793,15 +794,15 @@ void Patch::appendPoints(bool columns, bool beginning) {
// Extrapolate the vertex attributes of the rows
// These are the indices of the new rows
- std::size_t newRow1 = beginning ? 0 : m_height - 1; // The outermost row
- std::size_t newRow2 = beginning ? 1 : m_height - 2; // The nearest row
+ std::size_t newRow1 = beginning ? 0 : _height - 1; // The outermost row
+ std::size_t newRow2 = beginning ? 1 : _height - 2; // The nearest row
// This indicates the direction we are taking the base values from
// If we start at the beginning, we have to take the values on
// the "right", hence the +1 index
int neighbour = beginning ? +1 : -1;
- for (std::size_t col = 0; col < m_width; col++) {
+ for (std::size_t col = 0; col < _width; col++) {
// The distance of the two neighbouring rows,
// this is taken as extrapolation value
Vector3 vertexDiff = ctrlAt(newRow2 + neighbour, col).vertex -
@@ -829,12 +830,12 @@ Patch* Patch::MakeCap(Patch* patch, EPatchCap eType, EMatrixMajor mt, bool bFirs
switch(mt)
{
case ROW:
- width = m_width;
- height = m_height;
+ width = _width;
+ height = _height;
break;
case COL:
- width = m_height;
- height = m_width;
+ width = _height;
+ height = _width;
break;
default:
ERROR_MESSAGE("neither row-major nor column-major");
@@ -870,7 +871,7 @@ void Patch::FlipTexture(int nAxis)
{
undoSave();
- for(PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+ for(PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i)
{
i->texcoord[nAxis] = -i->texcoord[nAxis];
}
@@ -883,7 +884,7 @@ void Patch::FlipTexture(int nAxis)
*/
void Patch::translateTexCoords(Vector2 translation) {
// Cycle through all control points and shift them in texture space
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
i->texcoord += translation;
}
}
@@ -904,7 +905,7 @@ void Patch::ScaleTexture(float s, float t)
{
undoSave();
- for(PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+ for(PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i)
{
(*i).texcoord[0] *= s;
(*i).texcoord[1] *= t;
@@ -920,7 +921,7 @@ void Patch::RotateTexture(float angle)
const double s = sin(degrees_to_radians(angle));
const double c = cos(degrees_to_radians(angle));
- for(PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i)
+ for(PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i)
{
const double x = i->texcoord[0];
const double y = i->texcoord[1];
@@ -942,23 +943,23 @@ void Patch::SetTextureRepeat(float s, float t)
* If we have a 4x4 patch and want to tile it 3x3, the distance
* from one control point to the next one has to cover 3/4 of a full texture,
* hence texture_x_repeat/patch_width and texture_y_repeat/patch_height.*/
- float sIncr = s / static_cast<float>(m_width - 1);
- float tIncr = t / static_cast<float>(m_height - 1);
+ float sIncr = s / static_cast<float>(_width - 1);
+ float tIncr = t / static_cast<float>(_height - 1);
// Set the pointer to the first control point
- PatchControlIter pDest = m_ctrl.begin();
+ PatchControlIter pDest = _ctrl.begin();
float tc = 0;
// Cycle through the patch matrix (row per row)
// Increment the <tc> counter by <tIncr> increment
- for (std::size_t h=0; h < m_height; h++, tc += tIncr)
+ for (std::size_t h=0; h < _height; h++, tc += tIncr)
{
float sc = 0;
// Cycle through the row points: reset sc to zero
// and increment it by sIncr at each step.
- for (std::size_t w = 0; w < m_width; w++, sc += sIncr)
+ for (std::size_t w = 0; w < _width; w++, sc += sIncr)
{
// Set the texture coordinates
pDest->texcoord[0] = sc;
@@ -972,37 +973,6 @@ void Patch::SetTextureRepeat(float s, float t)
controlPointsChanged();
}
-inline int texture_axis(const Vector3& normal)
-{
- // axis dominance order: Z, X, Y
- return (normal.x() >= normal.y()) ? (normal.x() > normal.z()) ? 0 : 2 : (normal.y() > normal.z()) ? 1 : 2;
-}
-
-void Patch::CapTexture() {
- const PatchControl& p1 = m_ctrl[m_width];
- const PatchControl& p2 = m_ctrl[m_width*(m_height-1)];
- const PatchControl& p3 = m_ctrl[(m_width*m_height)-1];
-
- Vector3 normal(g_vector3_identity);
-
- {
- Vector3 tmp( (p2.vertex - m_ctrl[0].vertex).crossProduct(p3.vertex - m_ctrl[0].vertex) );
- if(tmp != g_vector3_identity)
- {
- normal += tmp;
- }
- }
- {
- Vector3 tmp( (p1.vertex - p3.vertex).crossProduct(m_ctrl[0].vertex - p3.vertex) );
- if(tmp != g_vector3_identity)
- {
- normal += tmp;
- }
- }
-
- ProjectTexture(texture_axis(normal));
-}
-
/* uses longest parallel chord to calculate texture coords for each row/col
* greebo: The default texture scale is used when applying "Natural" texturing.
* Note: all the comments in this method are by myself, so be careful... ;)
@@ -1042,24 +1012,24 @@ void Patch::NaturalTexture() {
double tex = 0;
// Cycle through the patch width,
- for (std::size_t w=0; w<m_width; w++)
+ for (std::size_t w=0; w<_width; w++)
{
// Apply the currently active <tex> value to the control point texture coordinates.
- for (std::size_t h = 0; h < m_height; h++)
+ for (std::size_t h = 0; h < _height; h++)
{
// Set the x-coord (or better s-coord?) of the texture to tex.
// For the first width cycle this is tex=0, so the texture is not shifted at the first vertex
ctrlAt(h, w).texcoord[0] = static_cast<float>(tex);
}
- // If we reached the last row (m_width - 1) we are finished (all coordinates are applied)
- if (w + 1 == m_width)
+ // If we reached the last row (_width - 1) we are finished (all coordinates are applied)
+ if (w + 1 == _width)
break;
// Determine the longest distance to the next column.
{
// Again, cycle through the current column
- for (std::size_t h = 0; h < m_height; h++)
+ for (std::size_t h = 0; h < _height; h++)
{
// v is the vector pointing from one control point to the next neighbour
Vector3 v = ctrlAt(h, w).vertex - ctrlAt(h, w+1).vertex;
@@ -1095,18 +1065,18 @@ void Patch::NaturalTexture() {
double tex = 0;
// Each row is visited once
- for (std::size_t h = 0; h < m_height; h++)
+ for (std::size_t h = 0; h < _height; h++)
{
// During each row, we cycle through every height point
- for (std::size_t w = 0; w < m_width; w++)
+ for (std::size_t w = 0; w < _width; w++)
{
ctrlAt(h, w).texcoord[1] = static_cast<float>(tex);
}
- if (h + 1 == m_height)
+ if (h + 1 == _height)
break;
- for (std::size_t w = 0; w < m_width; w++)
+ for (std::size_t w = 0; w < _width; w++)
{
Vector3 v = ctrlAt(h, w).vertex - ctrlAt(h+1, w).vertex;
@@ -1130,15 +1100,15 @@ void Patch::updateAABB()
{
AABB aabb;
- for(PatchControlIter i = m_ctrlTransformed.begin(); i != m_ctrlTransformed.end(); ++i)
+ for(PatchControlIter i = _ctrlTransformed.begin(); i != _ctrlTransformed.end(); ++i)
{
aabb.includePoint(i->vertex);
}
// greebo: Only trigger the callbacks if the bounds actually changed
- if (m_aabb_local != aabb)
+ if (_localAABB != aabb)
{
- m_aabb_local = aabb;
+ _localAABB = aabb;
_node.boundsChanged();
_node.lightsChanged();
@@ -1147,28 +1117,28 @@ void Patch::updateAABB()
// Inserts two columns before and after the column having the index <colIndex>
void Patch::insertColumns(std::size_t colIndex) {
- if (colIndex == 0 || colIndex == m_width) {
+ if (colIndex == 0 || colIndex == _width) {
throw GenericPatchException("Patch::insertColumns: can't insert at this index.");
}
- if (m_width + 2 > MAX_PATCH_WIDTH) {
+ if (_width + 2 > MAX_PATCH_WIDTH) {
throw GenericPatchException("Patch::insertColumns: patch has too many columns.");
}
// Create a backup of the old control vertices
- PatchControlArray oldCtrl = m_ctrl;
- std::size_t oldHeight = m_height;
- std::size_t oldWidth = m_width;
+ PatchControlArray oldCtrl = _ctrl;
+ std::size_t oldHeight = _height;
+ std::size_t oldWidth = _width;
// Resize this patch
setDims(oldWidth + 2, oldHeight);
// Now fill in the control vertex values and interpolate
// before and after the insert point.
- for (std::size_t row = 0; row < m_height; row++) {
+ for (std::size_t row = 0; row < _height; row++) {
for (std::size_t newCol = 0, oldCol = 0;
- newCol < m_width && oldCol < oldWidth;
+ newCol < _width && oldCol < oldWidth;
newCol++, oldCol++)
{
// Is this the insert point?
@@ -1210,28 +1180,28 @@ void Patch::insertColumns(std::size_t colIndex) {
// Inserts two rows before and after the column having the index <colIndex>
void Patch::insertRows(std::size_t rowIndex) {
- if (rowIndex == 0 || rowIndex == m_height) {
+ if (rowIndex == 0 || rowIndex == _height) {
throw GenericPatchException("Patch::insertRows: can't insert at this index.");
}
- if (m_height + 2 > MAX_PATCH_HEIGHT) {
+ if (_height + 2 > MAX_PATCH_HEIGHT) {
throw GenericPatchException("Patch::insertRows: patch has too many rows.");
}
// Create a backup of the old control vertices
- PatchControlArray oldCtrl = m_ctrl;
- std::size_t oldHeight = m_height;
- std::size_t oldWidth = m_width;
+ PatchControlArray oldCtrl = _ctrl;
+ std::size_t oldHeight = _height;
+ std::size_t oldWidth = _width;
// Resize this patch
setDims(oldWidth, oldHeight + 2);
// Now fill in the control vertex values and interpolate
// before and after the insert point.
- for (std::size_t col = 0; col < m_width; col++) {
+ for (std::size_t col = 0; col < _width; col++) {
for (std::size_t newRow = 0, oldRow = 0;
- newRow < m_height && oldRow < oldHeight;
+ newRow < _height && oldRow < oldHeight;
newRow++, oldRow++)
{
// Is this the insert point?
@@ -1275,25 +1245,25 @@ void Patch::insertRows(std::size_t rowIndex) {
void Patch::removePoints(bool columns, std::size_t index) {
bool rows = !columns; // readability shortcut ;)
- if ((columns && m_width<5) || (!columns && m_height < 5))
+ if ((columns && _width<5) || (!columns && _height < 5))
{
throw GenericPatchException("Patch::removePoints: can't remove any more rows/columns.");
}
// Check column index bounds
- if (columns && (index < 2 || index > m_width - 3)) {
+ if (columns && (index < 2 || index > _width - 3)) {
throw GenericPatchException("Patch::removePoints: can't remove columns at this index.");
}
// Check row index bounds
- if (rows && (index < 2 || index > m_height - 3)) {
+ if (rows && (index < 2 || index > _height - 3)) {
throw GenericPatchException("Patch::removePoints: can't remove rows at this index.");
}
// Create a backup of the old control vertices
- PatchControlArray oldCtrl = m_ctrl;
- std::size_t oldHeight = m_height;
- std::size_t oldWidth = m_width;
+ PatchControlArray oldCtrl = _ctrl;
+ std::size_t oldHeight = _height;
+ std::size_t oldWidth = _width;
// Resize this patch
setDims(columns ? oldWidth - 2 : oldWidth, rows ? oldHeight - 2 : oldHeight);
@@ -1301,7 +1271,7 @@ void Patch::removePoints(bool columns, std::size_t index) {
// Now fill in the control vertex values and skip
// the rows/cols before and after the remove point.
for (std::size_t newRow = 0, oldRow = 0;
- newRow < m_height && oldRow < oldHeight;
+ newRow < _height && oldRow < oldHeight;
newRow++, oldRow++)
{
// Skip the row before and after the removal point
@@ -1311,7 +1281,7 @@ void Patch::removePoints(bool columns, std::size_t index) {
}
for (std::size_t oldCol = 0, newCol = 0;
- oldCol < oldWidth && newCol < m_width;
+ oldCol < oldWidth && newCol < _width;
oldCol++, newCol++)
{
// Skip the column before and after the removal point
@@ -1334,30 +1304,30 @@ void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
case eCapIBevel:
{
setDims(3, 3);
- m_ctrl[0].vertex = p[0];
- m_ctrl[1].vertex = p[1];
- m_ctrl[2].vertex = p[1];
- m_ctrl[3].vertex = p[1];
- m_ctrl[4].vertex = p[1];
- m_ctrl[5].vertex = p[1];
- m_ctrl[6].vertex = p[2];
- m_ctrl[7].vertex = p[1];
- m_ctrl[8].vertex = p[1];
+ _ctrl[0].vertex = p[0];
+ _ctrl[1].vertex = p[1];
+ _ctrl[2].vertex = p[1];
+ _ctrl[3].vertex = p[1];
+ _ctrl[4].vertex = p[1];
+ _ctrl[5].vertex = p[1];
+ _ctrl[6].vertex = p[2];
+ _ctrl[7].vertex = p[1];
+ _ctrl[8].vertex = p[1];
}
break;
case eCapBevel:
{
setDims(3, 3);
Vector3 p3(p[2] + (p[0] - p[1]));
- m_ctrl[0].vertex = p3;
- m_ctrl[1].vertex = p3;
- m_ctrl[2].vertex = p[2];
- m_ctrl[3].vertex = p3;
- m_ctrl[4].vertex = p3;
- m_ctrl[5].vertex = p[1];
- m_ctrl[6].vertex = p3;
- m_ctrl[7].vertex = p3;
- m_ctrl[8].vertex = p[0];
+ _ctrl[0].vertex = p3;
+ _ctrl[1].vertex = p3;
+ _ctrl[2].vertex = p[2];
+ _ctrl[3].vertex = p3;
+ _ctrl[4].vertex = p3;
+ _ctrl[5].vertex = p[1];
+ _ctrl[6].vertex = p3;
+ _ctrl[7].vertex = p3;
+ _ctrl[8].vertex = p[0];
}
break;
case eCapEndCap:
@@ -1365,35 +1335,35 @@ void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
Vector3 p5(p[0].mid(p[4]));
setDims(3, 3);
- m_ctrl[0].vertex = p[0];
- m_ctrl[1].vertex = p5;
- m_ctrl[2].vertex = p[4];
- m_ctrl[3].vertex = p[1];
- m_ctrl[4].vertex = p[2];
- m_ctrl[5].vertex = p[3];
- m_ctrl[6].vertex = p[2];
- m_ctrl[7].vertex = p[2];
- m_ctrl[8].vertex = p[2];
+ _ctrl[0].vertex = p[0];
+ _ctrl[1].vertex = p5;
+ _ctrl[2].vertex = p[4];
+ _ctrl[3].vertex = p[1];
+ _ctrl[4].vertex = p[2];
+ _ctrl[5].vertex = p[3];
+ _ctrl[6].vertex = p[2];
+ _ctrl[7].vertex = p[2];
+ _ctrl[8].vertex = p[2];
}
break;
case eCapIEndCap:
{
setDims(5, 3);
- m_ctrl[0].vertex = p[4];
- m_ctrl[1].vertex = p[3];
- m_ctrl[2].vertex = p[2];
- m_ctrl[3].vertex = p[1];
- m_ctrl[4].vertex = p[0];
- m_ctrl[5].vertex = p[3];
- m_ctrl[6].vertex = p[3];
- m_ctrl[7].vertex = p[2];
- m_ctrl[8].vertex = p[1];
- m_ctrl[9].vertex = p[1];
- m_ctrl[10].vertex = p[3];
- m_ctrl[11].vertex = p[3];
- m_ctrl[12].vertex = p[2];
- m_ctrl[13].vertex = p[1];
- m_ctrl[14].vertex = p[1];
+ _ctrl[0].vertex = p[4];
+ _ctrl[1].vertex = p[3];
+ _ctrl[2].vertex = p[2];
+ _ctrl[3].vertex = p[1];
+ _ctrl[4].vertex = p[0];
+ _ctrl[5].vertex = p[3];
+ _ctrl[6].vertex = p[3];
+ _ctrl[7].vertex = p[2];
+ _ctrl[8].vertex = p[1];
+ _ctrl[9].vertex = p[1];
+ _ctrl[10].vertex = p[3];
+ _ctrl[11].vertex = p[3];
+ _ctrl[12].vertex = p[2];
+ _ctrl[13].vertex = p[1];
+ _ctrl[14].vertex = p[1];
}
break;
case eCapCylinder:
@@ -1416,18 +1386,20 @@ void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
}
{
- PatchControlIter pCtrl = m_ctrl.begin();
- for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
+ PatchControlIter pCtrl = _ctrl.begin();
+ for(std::size_t i = 0; i != _height; ++i, pCtrl += _width)
{
pCtrl->vertex = p[i];
}
}
{
- PatchControlIter pCtrl = m_ctrl.begin() + 2;
- std::size_t h = m_height - 1;
- for(std::size_t i = 0; i != m_height; ++i, pCtrl += m_width)
+ PatchControlIter pCtrl = _ctrl.begin() + 2;
+ std::size_t h = _height - 1;
+ for(std::size_t i = 0; i != _height; ++i, pCtrl += _width)
{
pCtrl->vertex = p[h + (h - i)];
+
+ if (i == _height - 1) break; // prevent iterator from being incremented post bounds
}
}
@@ -1438,7 +1410,6 @@ void Patch::ConstructSeam(EPatchCap eType, Vector3* p, std::size_t width)
ERROR_MESSAGE("invalid patch-cap type");
return;
}
- CapTexture();
controlPointsChanged();
}
@@ -1452,14 +1423,14 @@ PatchControlIter Patch::getClosestPatchControlToPoint(const Vector3& point) {
double closestDist = -1.0;
PatchControlIter corners[4] = {
- m_ctrl.begin(),
- m_ctrl.begin() + (m_width-1),
- m_ctrl.begin() + (m_width*(m_height-1)),
- m_ctrl.begin() + (m_width*m_height - 1)
+ _ctrl.begin(),
+ _ctrl.begin() + (_width-1),
+ _ctrl.begin() + (_width*(_height-1)),
+ _ctrl.begin() + (_width*_height - 1)
};
// Cycle through all the control points with an iterator
- //for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ //for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
for (unsigned int i = 0; i < 4; i++) {
// Calculate the distance of the current vertex
@@ -1565,13 +1536,13 @@ Vector2 Patch::getPatchControlArrayIndices(const PatchControlIter& control)
std::size_t count = 0;
// Go through the patch column per column and find the control vertex
- for (PatchControlIter p = m_ctrl.begin(); p != m_ctrl.end(); ++p, ++count)
+ for (PatchControlIter p = _ctrl.begin(); p != _ctrl.end(); ++p, ++count)
{
// Compare the iterators to check if we have found the control
if (p == control)
{
- int row = static_cast<int>(floor(static_cast<float>(count) / m_width));
- int col = static_cast<int>(count % m_width);
+ int row = static_cast<int>(floor(static_cast<float>(count) / _width));
+ int col = static_cast<int>(count % _width);
return Vector2(col, row);
}
@@ -1621,8 +1592,8 @@ void Patch::pasteTextureNatural(const Face* face)
if (face == nullptr) return;
// Convert the size_t stuff into int, because we need it for signed comparisons
- int patchHeight = static_cast<int>(m_height);
- int patchWidth = static_cast<int>(m_width);
+ int patchHeight = static_cast<int>(_height);
+ int patchWidth = static_cast<int>(_width);
// Get the plane and its normalised normal vector of the face
Plane3 plane = face->getPlane().getPlane().getNormalised();
@@ -1648,15 +1619,15 @@ void Patch::pasteTextureNatural(const Face* face)
int hIncr = (hStart == patchHeight-1) ? -1 : 1;
int hEnd = (hIncr<0) ? -1 : patchHeight;
- PatchControl* startControl = &m_ctrl[(patchWidth*hStart) + wStart];
+ PatchControl* startControl = &_ctrl[(patchWidth*hStart) + wStart];
// Calculate the base directions that are used to "flatten" the patch
// These have to be orthogonal to the facePlane normal, so that the texture coordinates
// can be retrieved by projection onto the facePlane.
// Get the control points of the next column and the next row
- PatchControl& nextColumn = m_ctrl[(patchWidth*(hStart + hIncr)) + wStart];
- PatchControl& nextRow = m_ctrl[(patchWidth*hStart) + (wStart + wIncr)];
+ PatchControl& nextColumn = _ctrl[(patchWidth*(hStart + hIncr)) + wStart];
+ PatchControl& nextRow = _ctrl[(patchWidth*hStart) + (wStart + wIncr)];
// Calculate the world direction of these control points and extract a base
Vector3 widthVector = (nextRow.vertex - startControl->vertex);
@@ -1686,7 +1657,7 @@ void Patch::pasteTextureNatural(const Face* face)
for (int w = wStart; w != wEnd; w += wIncr) {
// The first control in this row, calculate its virtual coords
- PatchControl* curColumn = &m_ctrl[(patchWidth*hStart) + w];
+ PatchControl* curColumn = &_ctrl[(patchWidth*hStart) + w];
// The distance between the last column and this column
double xyzColDist = (curColumn->vertex - prevColumn->vertex).getLength();
@@ -1702,7 +1673,7 @@ void Patch::pasteTextureNatural(const Face* face)
for (int h = hStart; h != hEnd; h += hIncr) {
// The current control
- PatchControl* control = &m_ctrl[(patchWidth*h) + w];
+ PatchControl* control = &_ctrl[(patchWidth*h) + w];
// The distance between the last and the current vertex
double xyzRowDist = (control->vertex - prevRow->vertex).getLength();
@@ -1732,8 +1703,8 @@ void Patch::pasteTextureNatural(Patch& sourcePatch) {
undoSave();
// Convert the size_t stuff into int, because we need it for signed comparisons
- int patchHeight = static_cast<int>(m_height);
- int patchWidth = static_cast<int>(m_width);
+ int patchHeight = static_cast<int>(_height);
+ int patchWidth = static_cast<int>(_width);
// Calculate the nearest corner vertex of this patch (to the sourcepatch vertices)
PatchControlIter nearestControl = getClosestPatchControlToPatch(sourcePatch);
@@ -1773,7 +1744,7 @@ void Patch::pasteTextureProjected(const Face* face) {
Matrix4 worldToTexture = face->getProjection().getWorldToTexture(faceNormal, Matrix4::getIdentity());
// Cycle through all the control points with an iterator
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
// Project the vertex onto the face plane and transform it into texture space
i->texcoord = getProjectedTextureCoords(i->vertex, plane, worldToTexture);
}
@@ -1791,13 +1762,13 @@ void Patch::pasteTextureCoordinates(const Patch* otherPatch) {
if (otherPatch != NULL) {
- if (otherPatch->getWidth() == m_width && otherPatch->getHeight() == m_height) {
+ if (otherPatch->getWidth() == _width && otherPatch->getHeight() == _height) {
PatchControlConstIter other;
PatchControlIter self;
// Clone the texture coordinates one by one
- for (other = otherPatch->begin(), self = m_ctrl.begin();
+ for (other = otherPatch->begin(), self = _ctrl.begin();
other != otherPatch->end();
++other, ++self)
{
@@ -1813,63 +1784,6 @@ void Patch::pasteTextureCoordinates(const Patch* otherPatch) {
}
}
-/* greebo: This gets called when clicking on the "CAP" button in the surface dialogs.
- *
- * The texture is projected onto either the <x,y>, <y,z>, or <x,z> planes and the result
- * is not stretched in any direction, as the pure components of the vector are translated
- * into texture coordinates. Points on the x-axis that are near to each other get
- * texture coordinates that are "near" to each other.
- *
- * The argument nAxis can be 0,1,2 and determines, which components are taken to
- * calculate the texture coordinates.
- *
- * Note: the default texture scale is used to calculate the texture coordinates.
- */
-void Patch::ProjectTexture(int nAxis) {
- // Save the undo memento
- undoSave();
-
- // Hold the component index of the vector (e.g. 0,1 = x,y or 1,2 = y,z)
- int s, t;
-
- switch (nAxis) {
- case 2: // Projection onto <x,y> plane
- s = 0;
- t = 1;
- break;
- case 0: // Projection onto <y,z> plane
- s = 1;
- t = 2;
- break;
- case 1: // Projection onto <x,z> plane
- s = 0;
- t = 2;
- break;
- default:
- ERROR_MESSAGE("invalid axis");
- return;
- }
-
- // Retrieve the default scale from the registry
- float defaultScale = registry::getValue<float>("user/ui/defaultTextureScale");
-
- /* Calculate the conversion factor between world and texture coordinates
- * by using the image width/height.*/
- float fWidth = 1 / (_shader.getWidth() * defaultScale);
- float fHeight = 1 / (_shader.getHeight() * -defaultScale);
-
- // Cycle through all the control points with an iterator
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
- // Take the according value (e.g. s = x, t = y, depending on the nAxis argument)
- // and apply the appropriate texture coordinate
- i->texcoord[0] = i->vertex[s] * fWidth;
- i->texcoord[1] = i->vertex[t] * fHeight;
- }
-
- // Notify the patch about the change
- controlPointsChanged();
-}
-
void Patch::alignTexture(EAlignType align)
{
if (isDegenerate()) return;
@@ -1881,22 +1795,22 @@ void Patch::alignTexture(EAlignType align)
std::vector<Vector2> texCoords;
// Calculate all edges in texture space
- for (std::size_t h = 0; h < m_height-1; ++h)
+ for (std::size_t h = 0; h < _height-1; ++h)
{
- for (std::size_t w = 0; w < m_width-1; ++w)
+ for (std::size_t w = 0; w < _width-1; ++w)
{
texEdges.push_back(ctrlAt(0, w).texcoord - ctrlAt(0, w+1).texcoord);
texCoords.push_back(ctrlAt(0,w).texcoord);
- texEdges.push_back(ctrlAt(m_height-1, w+1).texcoord - ctrlAt(m_height-1, w).texcoord);
- texCoords.push_back(ctrlAt(m_height-1, w+1).texcoord);
+ texEdges.push_back(ctrlAt(_height-1, w+1).texcoord - ctrlAt(_height-1, w).texcoord);
+ texCoords.push_back(ctrlAt(_height-1, w+1).texcoord);
}
texEdges.push_back(ctrlAt(h, 0).texcoord - ctrlAt(h+1, 0).texcoord);
texCoords.push_back(ctrlAt(h, 0).texcoord);
- texEdges.push_back(ctrlAt(h+1, m_width-1).texcoord - ctrlAt(h, m_width-1).texcoord);
- texCoords.push_back(ctrlAt(h+1, m_width-1).texcoord);
+ texEdges.push_back(ctrlAt(h+1, _width-1).texcoord - ctrlAt(h, _width-1).texcoord);
+ texCoords.push_back(ctrlAt(h+1, _width-1).texcoord);
}
// Find the edge which is nearest to the s,t base vector, to classify them as "top" or "left"
@@ -1970,8 +1884,8 @@ PatchMesh Patch::getTesselatedPatchMesh() const
PatchMesh mesh;
- mesh.width = _mesh.m_nArrayWidth;
- mesh.height = _mesh.m_nArrayHeight;
+ mesh.width = _mesh.width;
+ mesh.height = _mesh.height;
for (std::vector<ArbitraryMeshVertex>::const_iterator i = _mesh.vertices.begin();
i != _mesh.vertices.end(); ++i)
@@ -2003,26 +1917,26 @@ void Patch::constructPlane(const AABB& aabb, int axis, std::size_t width, std::s
return;
}
- if(m_width < MIN_PATCH_WIDTH || m_width > MAX_PATCH_WIDTH) m_width = 3;
- if(m_height < MIN_PATCH_HEIGHT || m_height > MAX_PATCH_HEIGHT) m_height = 3;
+ if(_width < MIN_PATCH_WIDTH || _width > MAX_PATCH_WIDTH) _width = 3;
+ if(_height < MIN_PATCH_HEIGHT || _height > MAX_PATCH_HEIGHT) _height = 3;
Vector3 vStart;
vStart[x] = aabb.origin[x] - aabb.extents[x];
vStart[y] = aabb.origin[y] - aabb.extents[y];
vStart[z] = aabb.origin[z];
- float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float)(m_width - 1));
- float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float)(m_height - 1));
+ float xAdj = fabsf((vStart[x] - (aabb.origin[x] + aabb.extents[x])) / (float)(_width - 1));
+ float yAdj = fabsf((vStart[y] - (aabb.origin[y] + aabb.extents[y])) / (float)(_height - 1));
Vector3 vTmp;
vTmp[z] = vStart[z];
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
vTmp[y]=vStart[y];
- for (std::size_t h=0; h<m_height; h++)
+ for (std::size_t h=0; h<_height; h++)
{
vTmp[x]=vStart[x];
- for (std::size_t w=0; w<m_width; w++, ++pCtrl)
+ for (std::size_t w=0; w<_width; w++, ++pCtrl)
{
pCtrl->vertex = vTmp;
vTmp[x]+=xAdj;
@@ -2073,7 +1987,7 @@ void Patch::constructBevel(const AABB& aabb, EViewType viewType)
setDims(3, 3);
- PatchControlIter ctrl = m_ctrl.begin();
+ PatchControlIter ctrl = _ctrl.begin();
for (std::size_t h = 0; h < 3; ++h)
{
@@ -2120,7 +2034,7 @@ void Patch::constructEndcap(const AABB& aabb, EViewType viewType)
setDims(5, 3);
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
for (std::size_t h = 0; h < 3; ++h)
{
@@ -2171,20 +2085,20 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
{
case eSqCylinder:
setDims(9, 3);
- pStart = m_ctrl.begin();
+ pStart = _ctrl.begin();
break;
case eDenseCylinder:
case eVeryDenseCylinder:
case eCylinder:
setDims(9, 3);
- pStart = m_ctrl.begin() + 1;
+ pStart = _ctrl.begin() + 1;
break;
case eCone: setDims(9, 3);
- pStart = m_ctrl.begin() + 1;
+ pStart = _ctrl.begin() + 1;
break;
case eSphere:
setDims(9, 5);
- pStart = m_ctrl.begin() + (9+1);
+ pStart = _ctrl.begin() + (9+1);
break;
default:
ERROR_MESSAGE("this should be unreachable");
@@ -2243,7 +2157,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
{
case eSqCylinder:
{
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
for (std::size_t h = 0; h < 3; ++h)
{
@@ -2261,7 +2175,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
{
// Regular cylinders get the first column snapped to the last one
// to form a closed loop
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
for (std::size_t h = 0; h < 3; ++h)
{
@@ -2275,7 +2189,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
case eCone:
// Close the control vertex loop of cones
{
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
for (std::size_t h = 0; h < 2; ++h)
{
@@ -2286,7 +2200,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
}
// And "merge" the vertices of the last row into one single point
{
- PatchControlIter pCtrl = m_ctrl.begin() + 9*2;
+ PatchControlIter pCtrl = _ctrl.begin() + 9*2;
for (std::size_t w = 0; w < 9; ++w, ++pCtrl)
{
@@ -2299,7 +2213,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
case eSphere:
// Close the vertex loop for spheres too (middle row)
{
- PatchControlIter pCtrl = m_ctrl.begin() + 9;
+ PatchControlIter pCtrl = _ctrl.begin() + 9;
for (std::size_t h = 0; h < 3; ++h)
{
@@ -2311,7 +2225,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
}
// Merge the first and last row vertices into one single point
{
- PatchControlIter pCtrl = m_ctrl.begin();
+ PatchControlIter pCtrl = _ctrl.begin();
for (std::size_t w = 0; w < 9; ++w, ++pCtrl)
{
@@ -2321,7 +2235,7 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
}
}
{
- PatchControlIter pCtrl = m_ctrl.begin() + (9*4);
+ PatchControlIter pCtrl = _ctrl.begin() + (9*4);
for (std::size_t w = 0; w < 9; ++w, ++pCtrl)
{
@@ -2356,1507 +2270,198 @@ void Patch::ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType view
NaturalTexture();
}
-#define DEGEN_0a 0x01
-#define DEGEN_1a 0x02
-#define DEGEN_2a 0x04
-#define DEGEN_0b 0x08
-#define DEGEN_1b 0x10
-#define DEGEN_2b 0x20
-#define SPLIT 0x40
-#define AVERAGE 0x80
-
-
-unsigned int subarray_get_degen(PatchControlIter subarray, std::size_t strideU, std::size_t strideV)
-{
- unsigned int nDegen = 0;
- PatchControlIter p1;
- PatchControlIter p2;
-
- p1 = subarray;
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_0a;
- p1 = p2;
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_0b;
-
- p1 = subarray + strideV;
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_1a;
- p1 = p2;
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_1b;
-
- p1 = subarray + (strideV << 1);
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_2a;
- p1 = p2;
- p2 = p1 + strideU;
- if(p1->vertex == p2->vertex)
- nDegen |= DEGEN_2b;
-
- return nDegen;
-}
-
-
-inline void deCasteljau3(const Vector3& P0, const Vector3& P1, const Vector3& P2, Vector3& P01, Vector3& P12, Vector3& P012)
-{
- P01 = P0.mid(P1);
- P12 = P1.mid(P2);
- P012 = P01.mid(P12);
-}
-
-inline void BezierInterpolate3( const Vector3& start, Vector3& left, Vector3& mid, Vector3& right, const Vector3& end )
-{
- left = start.mid(mid);
- right = mid.mid(end);
- mid = left.mid(right);
-}
-
-inline void BezierInterpolate2( const Vector2& start, Vector2& left, Vector2& mid, Vector2& right, const Vector2& end )
-{
- left[0]= float_mid(start[0], mid[0]);
- left[1] = float_mid(start[1], mid[1]);
- right[0] = float_mid(mid[0], end[0]);
- right[1] = float_mid(mid[1], end[1]);
- mid[0] = float_mid(left[0], right[0]);
- mid[1] = float_mid(left[1], right[1]);
-}
-
-#include "math/curve.h"
-
-inline PatchControl QuadraticBezier_evaluate(const PatchControl* firstPoint, double t)
+Vector3 getAverageNormal(const Vector3& normal1, const Vector3& normal2, double thickness)
{
- PatchControl result = { Vector3(0, 0, 0), Vector2(0, 0) };
- double denominator = 0;
+ // Beware of normals with 0 length
+ if (normal1.getLengthSquared() == 0) return normal2;
+ if (normal2.getLengthSquared() == 0) return normal1;
- {
- double weight = BernsteinPolynomial<Zero, Two>::apply(t);
- result.vertex += firstPoint[0].vertex * weight;
- result.texcoord += firstPoint[0].texcoord * weight;
- denominator += weight;
- }
- {
- double weight = BernsteinPolynomial<One, Two>::apply(t);
- result.vertex += firstPoint[1].vertex * weight;
- result.texcoord += firstPoint[1].texcoord * weight;
- denominator += weight;
- }
- {
- double weight = BernsteinPolynomial<Two, Two>::apply(t);
- result.vertex += firstPoint[2].vertex * weight;
- result.texcoord += firstPoint[2].texcoord * weight;
- denominator += weight;
- }
+ // Both normals have length > 0
+ Vector3 n1 = normal1.getNormalised();
+ Vector3 n2 = normal2.getNormalised();
- result.vertex /= denominator;
- result.texcoord /= denominator;
- return result;
-}
+ // Get the angle bisector
+ Vector3 normal = (n1 + n2).getNormalised();
-inline Vector3 vector3_linear_interpolated(const Vector3& a, const Vector3& b, double t)
-{
- return a*(1.0 - t) + b*t;
-}
+ // Now calculate the length correction out of the angle
+ // of the two normals
+ float factor = cos(n1.angle(n2) * 0.5);
-inline Vector2 vector2_linear_interpolated(const Vector2& a, const Vector2& b, double t)
-{
- return a*(1.0 - t) + b*t;
-}
+ // Stretch the normal to fit the required thickness
+ normal *= thickness;
-void normalise_safe(Vector3& normal)
-{
- if (normal != g_vector3_identity)
+ // Check for div by zero (if the normals are antiparallel)
+ // and stretch the resulting normal, if necessary
+ if (factor != 0)
{
- normal.normalise();
+ normal /= factor;
}
-}
-inline void QuadraticBezier_evaluate(const PatchControl& a, const PatchControl& b, const PatchControl& c, double t, PatchControl& point, PatchControl& left, PatchControl& right)
-{
- left.vertex = vector3_linear_interpolated(a.vertex, b.vertex, t);
- left.texcoord = vector2_linear_interpolated(a.texcoord, b.texcoord, t);
- right.vertex = vector3_linear_interpolated(b.vertex, c.vertex, t);
- right.texcoord = vector2_linear_interpolated(b.texcoord, c.texcoord, t);
- point.vertex = vector3_linear_interpolated(left.vertex, right.vertex, t);
- point.texcoord = vector2_linear_interpolated(left.texcoord, right.texcoord, t);
+ return normal;
}
-void Patch::TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices,
- std::size_t strideX, std::size_t strideY,
- unsigned int nFlagsX, unsigned int nFlagsY,
- PatchControlIter subMatrix[3][3])
+void Patch::createThickenedOpposite(const Patch& sourcePatch,
+ const float thickness,
+ const int axis)
{
- double incrementU = 1.0 / m_subdivisions_x;
- double incrementV = 1.0 / m_subdivisions_y;
- const std::size_t width = m_subdivisions_x + 1;
- const std::size_t height = m_subdivisions_y + 1;
-
- for(std::size_t i = 0; i != width; ++i)
- {
- double tU = (i + 1 == width) ? 1 : i * incrementU;
- PatchControl pointX[3];
- PatchControl leftX[3];
- PatchControl rightX[3];
- QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[0][1], *subMatrix[0][2], tU, pointX[0], leftX[0], rightX[0]);
- QuadraticBezier_evaluate(*subMatrix[1][0], *subMatrix[1][1], *subMatrix[1][2], tU, pointX[1], leftX[1], rightX[1]);
- QuadraticBezier_evaluate(*subMatrix[2][0], *subMatrix[2][1], *subMatrix[2][2], tU, pointX[2], leftX[2], rightX[2]);
-
- ArbitraryMeshVertex* p = vertices + i * strideX;
- for(std::size_t j = 0; j != height; ++j)
- {
- if((j == 0 || j + 1 == height) && (i == 0 || i + 1 == width))
- {
- }
- else
- {
- double tV = (j + 1 == height) ? 1 : j * incrementV;
-
- PatchControl pointY[3];
- PatchControl leftY[3];
- PatchControl rightY[3];
- QuadraticBezier_evaluate(*subMatrix[0][0], *subMatrix[1][0], *subMatrix[2][0], tV, pointY[0], leftY[0], rightY[0]);
- QuadraticBezier_evaluate(*subMatrix[0][1], *subMatrix[1][1], *subMatrix[2][1], tV, pointY[1], leftY[1], rightY[1]);
- QuadraticBezier_evaluate(*subMatrix[0][2], *subMatrix[1][2], *subMatrix[2][2], tV, pointY[2], leftY[2], rightY[2]);
-
- PatchControl point;
- PatchControl left;
- PatchControl right;
- QuadraticBezier_evaluate(pointX[0], pointX[1], pointX[2], tV, point, left, right);
- PatchControl up;
- PatchControl down;
- QuadraticBezier_evaluate(pointY[0], pointY[1], pointY[2], tU, point, up, down);
-
- p->vertex = Vertex3f(point.vertex);
- p->texcoord = point.texcoord;
-
- ArbitraryMeshVertex a, b, c;
-
- a.vertex = Vertex3f(left.vertex);
- a.texcoord = left.texcoord;
- b.vertex = Vertex3f(right.vertex);
- b.texcoord = right.texcoord;
-
- if(i != 0)
- {
- c.vertex = Vertex3f(up.vertex);
- c.texcoord = up.texcoord;
- }
- else
- {
- c.vertex = Vertex3f(down.vertex);
- c.texcoord = down.texcoord;
- }
+ // Clone the dimensions from the other patch
+ setDims(sourcePatch.getWidth(), sourcePatch.getHeight());
- Vector3 normal = (right.vertex - left.vertex).crossProduct(up.vertex - down.vertex).getNormalised();
+ // Also inherit the tesselation from the source patch
+ setFixedSubdivisions(sourcePatch.subdivisionsFixed(), sourcePatch.getSubdivisions());
- Vector3 tangent, bitangent;
- ArbitraryMeshTriangle_calcTangents(a, b, c, tangent, bitangent);
- tangent = tangent.getNormalised();
- bitangent = bitangent.getNormalised();
+ // Copy the shader from the source patch
+ setShader(sourcePatch.getShader());
- if(((nFlagsX & AVERAGE) != 0 && i == 0) || ((nFlagsY & AVERAGE) != 0 && j == 0))
- {
- p->normal = Normal3f(p->normal + normal.getNormalised());
- p->tangent = Normal3f(p->tangent + tangent.getNormalised());
- p->bitangent = Normal3f((p->bitangent + bitangent).getNormalised());
- }
- else
- {
- p->normal = Normal3f(normal);
- p->tangent = Normal3f(tangent);
- p->bitangent = Normal3f(bitangent);
- }
- }
+ // if extrudeAxis == 0,0,0 the patch is extruded along its vertex normals
+ Vector3 extrudeAxis(0,0,0);
- p += strideY;
- }
- }
-}
+ switch (axis) {
+ case 0: // X-Axis
+ extrudeAxis = Vector3(1,0,0);
+ break;
+ case 1: // Y-Axis
+ extrudeAxis = Vector3(0,1,0);
+ break;
+ case 2: // Z-Axis
+ extrudeAxis = Vector3(0,0,1);
+ break;
+ default:
+ // Default value already set during initialisation
+ break;
+ }
-void Patch::TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
- std::size_t offStartX, std::size_t offStartY,
- std::size_t offEndX, std::size_t offEndY,
- std::size_t nFlagsX, std::size_t nFlagsY,
- Vector3& left, Vector3& mid, Vector3& right,
- Vector2& texLeft, Vector2& texMid, Vector2& texRight,
- bool bTranspose )
-{
- int newFlagsX, newFlagsY;
+ for (std::size_t col = 0; col < _width; col++)
+ {
+ for (std::size_t row = 0; row < _height; row++)
+ {
+ // The current control vertex on the other patch
+ const PatchControl& curCtrl = sourcePatch.ctrlAt(row, col);
- Vector3 tmp;
- Vector3 vertex_0_0, vertex_0_1, vertex_1_0, vertex_1_1, vertex_2_0, vertex_2_1;
- Vector2 texTmp;
- Vector2 texcoord_0_0, texcoord_0_1, texcoord_1_0, texcoord_1_1, texcoord_2_0, texcoord_2_1;
+ Vector3 normal;
- {
- // texcoords
+ // Are we extruding along vertex normals (i.e. extrudeAxis == 0,0,0)?
+ if (extrudeAxis == Vector3(0,0,0))
+ {
+ // The col tangents (empty if 0,0,0)
+ Vector3 colTangent[2] = { Vector3(0,0,0), Vector3(0,0,0) };
- BezierInterpolate2( _mesh.vertices[offStartX + offStartY].texcoord,
- texcoord_0_0,
- _mesh.vertices[BX->index + offStartY].texcoord,
- texcoord_0_1,
- _mesh.vertices[offEndX + offStartY].texcoord);
+ // Are we at the beginning/end of the column?
+ if (col == 0 || col == _width - 1)
+ {
+ // Get the next row index
+ std::size_t nextCol = (col == _width - 1) ? (col - 1) : (col + 1);
+ const PatchControl& colNeighbour = sourcePatch.ctrlAt(row, nextCol);
- BezierInterpolate2( _mesh.vertices[offStartX + offEndY].texcoord,
- texcoord_2_0,
- _mesh.vertices[BX->index + offEndY].texcoord,
- texcoord_2_1,
- _mesh.vertices[offEndX + offEndY].texcoord);
+ // One available tangent
+ colTangent[0] = colNeighbour.vertex - curCtrl.vertex;
+ // Reverse it if we're at the end of the column
+ colTangent[0] *= (col == _width - 1) ? -1 : +1;
+ }
+ // We are in between, two tangents can be calculated
+ else
+ {
+ // Take two neighbouring vertices that should form a line segment
+ const PatchControl& neighbour1 = sourcePatch.ctrlAt(row, col+1);
+ const PatchControl& neighbour2 = sourcePatch.ctrlAt(row, col-1);
- texTmp = texMid;
+ // Calculate both available tangents
+ colTangent[0] = neighbour1.vertex - curCtrl.vertex;
+ colTangent[1] = neighbour2.vertex - curCtrl.vertex;
- BezierInterpolate2(texLeft,
- texcoord_1_0,
- texTmp,
- texcoord_1_1,
- texRight);
+ // Reverse the second one
+ colTangent[1] *= -1;
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->index + BY->index].texcoord = texTmp;
- }
+ // Cull redundant tangents
+ if (colTangent[1].isParallel(colTangent[0]))
+ {
+ colTangent[1] = Vector3(0,0,0);
+ }
+ }
+ // Calculate the tangent vectors to the next row
+ Vector3 rowTangent[2] = { Vector3(0,0,0), Vector3(0,0,0) };
- if(!BX->left->isLeaf())
- {
- _mesh.vertices[BX->left->index + offStartY].texcoord = texcoord_0_0;
- _mesh.vertices[BX->left->index + offEndY].texcoord = texcoord_2_0;
+ // Are we at the beginning or the end?
+ if (row == 0 || row == _height - 1)
+ {
+ // Yes, only calculate one row tangent
+ // Get the next row index
+ std::size_t nextRow = (row == _height - 1) ? (row - 1) : (row + 1);
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->left->index + BY->index].texcoord = texcoord_1_0;
- }
- }
- if(!BX->right->isLeaf())
- {
- _mesh.vertices[BX->right->index + offStartY].texcoord = texcoord_0_1;
- _mesh.vertices[BX->right->index + offEndY].texcoord = texcoord_2_1;
+ const PatchControl& rowNeighbour = sourcePatch.ctrlAt(nextRow, col);
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->right->index + BY->index].texcoord = texcoord_1_1;
- }
- }
+ // First tangent
+ rowTangent[0] = rowNeighbour.vertex - curCtrl.vertex;
+ // Reverse it accordingly
+ rowTangent[0] *= (row == _height - 1) ? -1 : +1;
+ }
+ else
+ {
+ // Two tangents to calculate
+ const PatchControl& rowNeighbour1 = sourcePatch.ctrlAt(row + 1, col);
+ const PatchControl& rowNeighbour2 = sourcePatch.ctrlAt(row - 1, col);
+ // First tangent
+ rowTangent[0] = rowNeighbour1.vertex - curCtrl.vertex;
+ rowTangent[1] = rowNeighbour2.vertex - curCtrl.vertex;
- // verts
+ // Reverse the second one
+ rowTangent[1] *= -1;
- BezierInterpolate3( _mesh.vertices[offStartX + offStartY].vertex,
- vertex_0_0,
- _mesh.vertices[BX->index + offStartY].vertex,
- vertex_0_1,
- _mesh.vertices[offEndX + offStartY].vertex);
+ // Cull redundant tangents
+ if (rowTangent[1].isParallel(rowTangent[0]))
+ {
+ rowTangent[1] = Vector3(0,0,0);
+ }
+ }
+ // If two column tangents are available, take the length-corrected average
+ if (colTangent[1].getLengthSquared() > 0)
+ {
+ // Two column normals to calculate
+ Vector3 normal1 = rowTangent[0].crossProduct(colTangent[0]).getNormalised();
+ Vector3 normal2 = rowTangent[0].crossProduct(colTangent[1]).getNormalised();
- BezierInterpolate3( _mesh.vertices[offStartX + offEndY].vertex,
- vertex_2_0,
- _mesh.vertices[BX->index + offEndY].vertex,
- vertex_2_1,
- _mesh.vertices[offEndX + offEndY].vertex);
+ normal = getAverageNormal(normal1, normal2, thickness);
+ // Scale the normal down, as it is multiplied with thickness later on
+ normal /= thickness;
+ }
+ else
+ {
+ // One column tangent available, maybe we have a second rowtangent?
+ if (rowTangent[1].getLengthSquared() > 0)
+ {
+ // Two row normals to calculate
+ Vector3 normal1 = rowTangent[0].crossProduct(colTangent[0]).getNormalised();
+ Vector3 normal2 = rowTangent[1].crossProduct(colTangent[0]).getNormalised();
- tmp = mid;
+ normal = getAverageNormal(normal1, normal2, thickness);
- BezierInterpolate3( left,
- vertex_1_0,
- tmp,
- vertex_1_1,
- right );
+ // Scale the normal down, as it is multiplied with thickness later on
+ normal /= thickness;
+ }
+ else
+ {
+ normal = rowTangent[0].crossProduct(colTangent[0]);
+
+ if (normal.getLengthSquared() > 0)
+ {
+ normal.normalise();
+ }
+ }
+ }
+ }
+ else
+ {
+ // Take the predefined extrude direction instead
+ normal = extrudeAxis;
+ }
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->index + BY->index].vertex = tmp;
- }
-
-
- if(!BX->left->isLeaf())
- {
- _mesh.vertices[BX->left->index + offStartY].vertex = vertex_0_0;
- _mesh.vertices[BX->left->index + offEndY].vertex = vertex_2_0;
-
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->left->index + BY->index].vertex = vertex_1_0;
- }
- }
- if(!BX->right->isLeaf())
- {
- _mesh.vertices[BX->right->index + offStartY].vertex = vertex_0_1;
- _mesh.vertices[BX->right->index + offEndY].vertex = vertex_2_1;
-
- if(!BY->isLeaf())
- {
- _mesh.vertices[BX->right->index + BY->index].vertex = vertex_1_1;
- }
- }
-
- // normals
-
- if(nFlagsX & SPLIT)
- {
- ArbitraryMeshVertex a, b, c;
- Vector3 tangentU;
-
- if(!(nFlagsX & DEGEN_0a) || !(nFlagsX & DEGEN_0b))
- {
- tangentU = vertex_0_1 - vertex_0_0;
- a.vertex = Vertex3f(vertex_0_0);
- a.texcoord = texcoord_0_0;
- c.vertex = Vertex3f(vertex_0_1);
- c.texcoord = texcoord_0_1;
- }
- else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
- {
- tangentU = vertex_1_1 - vertex_1_0;
- a.vertex = Vertex3f(vertex_1_0);
- a.texcoord = texcoord_1_0;
- c.vertex = Vertex3f(vertex_1_1);
- c.texcoord = texcoord_1_1;
- }
- else
- {
- tangentU = vertex_2_1 - vertex_2_0;
- a.vertex = Vertex3f(vertex_2_0);
- a.texcoord = texcoord_2_0;
- c.vertex = Vertex3f(vertex_2_1);
- c.texcoord = texcoord_2_1;
- }
-
- Vector3 tangentV;
-
- if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
- {
- tangentV = _mesh.vertices[BX->index + offEndY].vertex - tmp;
- b.vertex = Vertex3f(tmp);//_mesh.vertices[BX->index + offEndY].vertex;
- b.texcoord = texTmp;//_mesh.vertices[BX->index + offEndY].texcoord;
- }
- else
- {
- tangentV = tmp - _mesh.vertices[BX->index + offStartY].vertex;
- b.vertex = Vertex3f(tmp);//_mesh.vertices[BX->index + offStartY].vertex;
- b.texcoord = texTmp; //_mesh.vertices[BX->index + offStartY].texcoord;
- }
-
-
- Vector3 normal, s, t;
- ArbitraryMeshVertex& v = _mesh.vertices[offStartY + BX->index];
- Vector3& p = v.normal;
- Vector3& ps = v.tangent;
- Vector3& pt = v.bitangent;
-
- if(bTranspose)
- {
- normal = tangentV.crossProduct(tangentU);
- }
- else
- {
- normal = tangentU.crossProduct(tangentV);
- }
- normalise_safe(normal);
-
- ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
- normalise_safe(s);
- normalise_safe(t);
-
- if(nFlagsX & AVERAGE)
- {
- p = (p + normal).getNormalised();
- ps = (ps + s).getNormalised();
- pt = (pt + t).getNormalised();
- }
- else
- {
- p = normal;
- ps = s;
- pt = t;
- }
- }
-
- {
- ArbitraryMeshVertex a, b, c;
- Vector3 tangentU;
-
- if(!(nFlagsX & DEGEN_2a) || !(nFlagsX & DEGEN_2b))
- {
- tangentU = vertex_2_1 - vertex_2_0;
- a.vertex = Vertex3f(vertex_2_0);
- a.texcoord = texcoord_2_0;
- c.vertex = Vertex3f(vertex_2_1);
- c.texcoord = texcoord_2_1;
- }
- else if(!(nFlagsX & DEGEN_1a) || !(nFlagsX & DEGEN_1b))
- {
- tangentU = vertex_1_1 - vertex_1_0;
- a.vertex = Vertex3f(vertex_1_0);
- a.texcoord = texcoord_1_0;
- c.vertex = Vertex3f(vertex_1_1);
- c.texcoord = texcoord_1_1;
- }
- else
- {
- tangentU = vertex_0_1 - vertex_0_0;
- a.vertex = Vertex3f(vertex_0_0);
- a.texcoord = texcoord_0_0;
- c.vertex = Vertex3f(vertex_0_1);
- c.texcoord = texcoord_0_1;
- }
-
- Vector3 tangentV;
-
- if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
- {
- tangentV = tmp - _mesh.vertices[BX->index + offStartY].vertex;
- b.vertex = Vertex3f(tmp);//_mesh.vertices[BX->index + offStartY].vertex;
- b.texcoord = texTmp;//_mesh.vertices[BX->index + offStartY].texcoord;
- }
- else
- {
- tangentV = _mesh.vertices[BX->index + offEndY].vertex - tmp;
- b.vertex = Vertex3f(tmp);//_mesh.vertices[BX->index + offEndY].vertex;
- b.texcoord = texTmp;//_mesh.vertices[BX->index + offEndY].texcoord;
- }
-
- ArbitraryMeshVertex& v = _mesh.vertices[offEndY+BX->index];
- Vector3& p = v.normal;
- Vector3& ps = v.tangent;
- Vector3& pt = v.bitangent;
-
- if(bTranspose)
- {
- p = tangentV.crossProduct(tangentU);
- }
- else
- {
- p = tangentU.crossProduct(tangentV);
- }
- normalise_safe(p);
-
- ArbitraryMeshTriangle_calcTangents(a, b, c, ps, pt);
- normalise_safe(ps);
- normalise_safe(pt);
- }
- }
-
-
- newFlagsX = newFlagsY = 0;
-
- if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_0b))
- {
- newFlagsX |= DEGEN_0a;
- newFlagsX |= DEGEN_0b;
- }
- if((nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_1b))
- {
- newFlagsX |= DEGEN_1a;
- newFlagsX |= DEGEN_1b;
- }
- if((nFlagsX & DEGEN_2a) && (nFlagsX & DEGEN_2b))
- {
- newFlagsX |= DEGEN_2a;
- newFlagsX |= DEGEN_2b;
- }
- if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_1a) && (nFlagsY & DEGEN_2a))
- {
- newFlagsY |= DEGEN_0a;
- newFlagsY |= DEGEN_1a;
- newFlagsY |= DEGEN_2a;
- }
- if((nFlagsY & DEGEN_0b) && (nFlagsY & DEGEN_1b) && (nFlagsY & DEGEN_2b))
- {
- newFlagsY |= DEGEN_0b;
- newFlagsY |= DEGEN_1b;
- newFlagsY |= DEGEN_2b;
- }
-
-
- //if((nFlagsX & DEGEN_0a) && (nFlagsX & DEGEN_1a) && (nFlagsX & DEGEN_2a)) { newFlagsX |= DEGEN_0a; newFlagsX |= DEGEN_1a; newFlagsX |= DEGEN_2a; }
- //if((nFlagsX & DEGEN_0b) && (nFlagsX & DEGEN_1b) && (nFlagsX & DEGEN_2b)) { newFlagsX |= DEGEN_0b; newFlagsX |= DEGEN_1b; newFlagsX |= DEGEN_2b; }
-
- newFlagsX |= (nFlagsX & SPLIT);
- newFlagsX |= (nFlagsX & AVERAGE);
-
- if(!BY->isLeaf())
- {
- {
- int nTemp = newFlagsY;
-
- if((nFlagsY & DEGEN_0a) && (nFlagsY & DEGEN_0b))
- {
- newFlagsY |= DEGEN_0a;
- newFlagsY |= DEGEN_0b;
- }
- newFlagsY |= (nFlagsY & SPLIT);
- newFlagsY |= (nFlagsY & AVERAGE);
-
- Vector3& p = _mesh.vertices[BX->index+BY->index].vertex;
- Vector3 vTemp(p);
-
- Vector2& p2 = _mesh.vertices[BX->index+BY->index].texcoord;
- Vector2 stTemp(p2);
-
- TesselateSubMatrix( BY, BX->left,
- offStartY, offStartX,
- offEndY, BX->index,
- newFlagsY, newFlagsX,
- vertex_0_0, vertex_1_0, vertex_2_0,
- texcoord_0_0, texcoord_1_0, texcoord_2_0,
- !bTranspose );
-
- newFlagsY = nTemp;
- p = vTemp;
- p2 = stTemp;
- }
-
- if((nFlagsY & DEGEN_2a) && (nFlagsY & DEGEN_2b)) { newFlagsY |= DEGEN_2a; newFlagsY |= DEGEN_2b; }
-
- TesselateSubMatrix( BY, BX->right,
- offStartY, BX->index,
- offEndY, offEndX,
- newFlagsY, newFlagsX,
- vertex_0_1, vertex_1_1, vertex_2_1,
- texcoord_0_1, texcoord_1_1, texcoord_2_1,
- !bTranspose );
- }
- else
- {
- if(!BX->left->isLeaf())
- {
- TesselateSubMatrix( BX->left, BY,
- offStartX, offStartY,
- BX->index, offEndY,
- newFlagsX, newFlagsY,
- left, vertex_1_0, tmp,
- texLeft, texcoord_1_0, texTmp,
- bTranspose );
- }
-
- if(!BX->right->isLeaf())
- {
- TesselateSubMatrix( BX->right, BY,
- BX->index, offStartY,
- offEndX, offEndY,
- newFlagsX, newFlagsY,
- tmp, vertex_1_1, right,
- texTmp, texcoord_1_1, texRight,
- bTranspose );
- }
- }
-
-}
-
-void Patch::BuildTesselationCurves(EMatrixMajor major)
-{
- std::size_t nArrayStride, length, cross, strideU, strideV;
- switch(major)
- {
- case ROW:
- nArrayStride = 1;
- length = (m_width - 1) >> 1;
- cross = m_height;
- strideU = 1;
- strideV = m_width;
-
- if(!m_patchDef3)
- {
- BezierCurveTreeArray_deleteAll(_mesh.curveTreeU);
- }
-
- break;
- case COL:
- nArrayStride = _mesh.m_nArrayWidth;
- length = (m_height - 1) >> 1;
- cross = m_width;
- strideU = m_width;
- strideV = 1;
-
- if(!m_patchDef3)
- {
- BezierCurveTreeArray_deleteAll(_mesh.curveTreeV);
- }
-
- break;
- default:
- ERROR_MESSAGE("neither row-major nor column-major");
- return;
- }
-
- std::vector<std::size_t> arrayLength;
- std::vector<BezierCurveTree*> pCurveTree(length);
-
- std::size_t nArrayLength = 1;
-
- if (m_patchDef3)
- {
- // This is a patch using fixed tesselation (patchDef3)
- std::size_t subdivisions = (major == ROW) ? m_subdivisions_x : m_subdivisions_y;
-
- // Assign the fixed number of tesselations to each column
- arrayLength.resize(length, subdivisions);
- nArrayLength += subdivisions * length;
- }
- else
- {
- // Resize the array and calculate the values
- arrayLength.resize(length);
-
- // create a list of the horizontal control curves in each column of sub-patches
- // adaptively tesselate each horizontal control curve in the list
- // create a binary tree representing the combined tesselation of the list
- for (std::size_t i = 0; i != length; ++i)
- {
- PatchControlIter p1 = m_ctrlTransformed.begin() + (i * 2 * strideU);
-
- BezierCurveList curveList;
-
- for (std::size_t j = 0; j < cross; j += 2)
- {
- // directly taken from one row of control points
- {
- BezierCurve* pCurve = new BezierCurve(
- (p1+strideU)->vertex, // crd
- p1->vertex, // left
- (p1+(strideU<<1))->vertex // right
- );
-
- curveList.push_front(pCurve);
- }
-
- // Skip the rest if this is the last turn
- if (j+2 >= cross) break;
-
- PatchControlIter p2 = p1 + strideV;
- PatchControlIter p3 = p2 + strideV;
-
- // interpolated from three columns of control points
- {
- BezierCurve* pCurve = new BezierCurve(
- (p1+strideU)->vertex.mid((p3+strideU)->vertex), // crd
- p1->vertex.mid(p3->vertex), // left
- (p1+(strideU<<1))->vertex.mid((p3+(strideU<<1))->vertex) // right
- );
-
- pCurve->crd = pCurve->crd.mid((p2+strideU)->vertex);
- pCurve->left = pCurve->left.mid(p2->vertex);
- pCurve->right = pCurve->right.mid((p2+(strideU<<1))->vertex);
-
- curveList.push_front(pCurve);
- }
-
- p1 = p3;
- }
-
- // Sort the curve list into a BezierCurveTree
- pCurveTree[i] = new BezierCurveTree;
-
- BezierCurveTree_FromCurveList(pCurveTree[i], curveList);
-
- // The curve list is not needed anymore, free it
- std::for_each(curveList.begin(), curveList.end(), [] (BezierCurve* curve)
- {
- delete curve;
- });
-
- curveList.clear();
-
- // set up array indices for binary tree
- // accumulate subarray width
- std::size_t l = pCurveTree[i]->setup(nArrayLength, nArrayStride) - (nArrayLength - 1);
- arrayLength[i] = l;
-
- // accumulate total array width
- nArrayLength += l;
- }
- }
-
- switch(major)
- {
- case ROW:
- _mesh.m_nArrayWidth = nArrayLength;
- std::swap(_mesh.arrayWidth, arrayLength);
-
- if(!m_patchDef3)
- {
- std::swap(_mesh.curveTreeU, pCurveTree);
- }
- break;
- case COL:
- _mesh.m_nArrayHeight = nArrayLength;
- std::swap(_mesh.arrayHeight, arrayLength);
-
- if(!m_patchDef3)
- {
- std::swap(_mesh.curveTreeV, pCurveTree);
- }
- break;
- }
-}
-
-inline void vertex_assign_ctrl(ArbitraryMeshVertex& vertex, const PatchControl& ctrl)
-{
- vertex.vertex = Vertex3f(ctrl.vertex);
- vertex.texcoord = ctrl.texcoord;
-}
-
-inline void vertex_clear_normal(ArbitraryMeshVertex& vertex)
-{
- vertex.normal = Normal3f(0, 0, 0);
- vertex.tangent = Normal3f(0, 0, 0);
- vertex.bitangent = Normal3f(0, 0, 0);
-}
-
-inline void tangents_remove_degenerate(Vector3 tangents[6], Vector2 textureTangents[6], unsigned int flags)
-{
- if(flags & DEGEN_0a)
- {
- const std::size_t i =
- (flags & DEGEN_0b)
- ? (flags & DEGEN_1a)
- ? (flags & DEGEN_1b)
- ? (flags & DEGEN_2a)
- ? 5
- : 4
- : 3
- : 2
- : 1;
- tangents[0] = tangents[i];
- textureTangents[0] = textureTangents[i];
- }
- if(flags & DEGEN_0b)
- {
- const std::size_t i =
- (flags & DEGEN_0a)
- ? (flags & DEGEN_1b)
- ? (flags & DEGEN_1a)
- ? (flags & DEGEN_2b)
- ? 4
- : 5
- : 2
- : 3
- : 0;
- tangents[1] = tangents[i];
- textureTangents[1] = textureTangents[i];
- }
- if(flags & DEGEN_2a)
- {
- const std::size_t i =
- (flags & DEGEN_2b)
- ? (flags & DEGEN_1a)
- ? (flags & DEGEN_1b)
- ? (flags & DEGEN_0a)
- ? 1
- : 0
- : 3
- : 2
- : 5;
- tangents[4] = tangents[i];
- textureTangents[4] = textureTangents[i];
- }
- if(flags & DEGEN_2b)
- {
- const std::size_t i =
- (flags & DEGEN_2a)
- ? (flags & DEGEN_1b)
- ? (flags & DEGEN_1a)
- ? (flags & DEGEN_0b)
- ? 0
- : 1
- : 2
- : 3
- : 4;
- tangents[5] = tangents[i];
- textureTangents[5] = textureTangents[i];
- }
-}
-
-void bestTangents00(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
-{
- if(fabs(dot + length) < 0.001) // opposing direction = degenerate
- {
- if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
- {
- index0 = 2;
- index1 = 0;
- }
- else if(!(degenerateFlags & DEGEN_0b))
- {
- index0 = 0;
- index1 = 1;
- }
- else
- {
- index0 = 1;
- index1 = 0;
- }
- }
- else if(fabs(dot - length) < 0.001) // same direction = degenerate
- {
- if(degenerateFlags & DEGEN_0b)
- {
- index0 = 0;
- index1 = 1;
- }
- else
- {
- index0 = 1;
- index1 = 0;
- }
- }
-}
-
-void bestTangents01(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
-{
- if(fabs(dot - length) < 0.001) // same direction = degenerate
- {
- if(!(degenerateFlags & DEGEN_1a)) // if this tangent is degenerate we cannot use it
- {
- index0 = 2;
- index1 = 1;
- }
- else if(!(degenerateFlags & DEGEN_2b))
- {
- index0 = 4;
- index1 = 0;
- }
- else
- {
- index0 = 5;
- index1 = 1;
- }
- }
- else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
- {
- if(degenerateFlags & DEGEN_2b)
- {
- index0 = 4;
- index1 = 0;
- }
- else
- {
- index0 = 5;
- index1 = 1;
- }
- }
-}
-
-void bestTangents10(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
-{
- if(fabs(dot - length) < 0.001) // same direction = degenerate
- {
- if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
- {
- index0 = 3;
- index1 = 4;
- }
- else if(!(degenerateFlags & DEGEN_0a))
- {
- index0 = 1;
- index1 = 5;
- }
- else
- {
- index0 = 0;
- index1 = 4;
- }
- }
- else if(fabs(dot + length) < 0.001) // opposing direction = degenerate
- {
- if(degenerateFlags & DEGEN_0a)
- {
- index0 = 1;
- index1 = 5;
- }
- else
- {
- index0 = 0;
- index1 = 4;
- }
- }
-}
-
-void bestTangents11(unsigned int degenerateFlags, double dot, double length, std::size_t& index0, std::size_t& index1)
-{
- if(fabs(dot + length) < 0.001) // opposing direction = degenerate
- {
- if(!(degenerateFlags & DEGEN_1b)) // if this tangent is degenerate we cannot use it
- {
- index0 = 3;
- index1 = 5;
- }
- else if(!(degenerateFlags & DEGEN_2a))
- {
- index0 = 5;
- index1 = 4;
- }
- else
- {
- index0 = 4;
- index1 = 5;
- }
- }
- else if(fabs(dot - length) < 0.001) // same direction = degenerate
- {
- if(degenerateFlags & DEGEN_2a)
- {
- index0 = 5;
- index1 = 4;
- }
- else
- {
- index0 = 4;
- index1 = 5;
- }
- }
-}
-
-void Patch::accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1)
-{
- {
- Vector3 normal(tangentX[index0].crossProduct(tangentY[index1]));
- if(normal != g_vector3_identity)
- {
- _mesh.vertices[index].normal += normal.getNormalised();
- }
- }
-
- {
- ArbitraryMeshVertex a, b, c;
- a.vertex = Vertex3f(0, 0, 0);
- a.texcoord = TexCoord2f(0, 0);
- b.vertex = Vertex3f(tangentX[index0]);
- b.texcoord = tangentS[index0];
- c.vertex = Vertex3f(tangentY[index1]);
- c.texcoord = tangentT[index1];
-
- Vector3 s, t;
- ArbitraryMeshTriangle_calcTangents(a, b, c, s, t);
- if(s != g_vector3_identity)
- {
- _mesh.vertices[index].tangent += s.getNormalised();
- }
- if(t != g_vector3_identity)
- {
- _mesh.vertices[index].bitangent += t.getNormalised();
- }
- }
-}
-
-const std::size_t PATCH_MAX_VERTEX_ARRAY = 1048576;
-
-void Patch::BuildVertexArray()
-{
- const std::size_t strideU = 1;
- const std::size_t strideV = m_width;
-
- const std::size_t numElems = _mesh.m_nArrayWidth*_mesh.m_nArrayHeight; // total number of elements in vertex array
-
- const bool bWidthStrips = (_mesh.m_nArrayWidth >= _mesh.m_nArrayHeight); // decide if horizontal strips are longer than vertical
-
-
- // allocate vertex, normal, texcoord and primitive-index arrays
- _mesh.vertices.resize(numElems);
- _mesh.indices.resize(_mesh.m_nArrayWidth *2 * (_mesh.m_nArrayHeight - 1));
-
- // set up strip indices
- if(bWidthStrips)
- {
- _mesh.m_numStrips = _mesh.m_nArrayHeight-1;
- _mesh.m_lenStrips = _mesh.m_nArrayWidth*2;
-
- for(std::size_t i=0; i<_mesh.m_nArrayWidth; i++)
- {
- for(std::size_t j=0; j<_mesh.m_numStrips; j++)
- {
- _mesh.indices[(j*_mesh.m_lenStrips)+i*2] = RenderIndex(j*_mesh.m_nArrayWidth+i);
- _mesh.indices[(j*_mesh.m_lenStrips)+i*2+1] = RenderIndex((j+1)*_mesh.m_nArrayWidth+i);
- // reverse because radiant uses CULL_FRONT
- //_mesh.indices[(j*_mesh.m_lenStrips)+i*2+1] = RenderIndex(j*_mesh.m_nArrayWidth+i);
- //_mesh.indices[(j*_mesh.m_lenStrips)+i*2] = RenderIndex((j+1)*_mesh.m_nArrayWidth+i);
- }
- }
- }
- else
- {
- _mesh.m_numStrips = _mesh.m_nArrayWidth-1;
- _mesh.m_lenStrips = _mesh.m_nArrayHeight*2;
-
- for(std::size_t i=0; i<_mesh.m_nArrayHeight; i++)
- {
- for(std::size_t j=0; j<_mesh.m_numStrips; j++)
- {
- _mesh.indices[(j*_mesh.m_lenStrips)+i*2] = RenderIndex(((_mesh.m_nArrayHeight-1)-i)*_mesh.m_nArrayWidth+j);
- _mesh.indices[(j*_mesh.m_lenStrips)+i*2+1] = RenderIndex(((_mesh.m_nArrayHeight-1)-i)*_mesh.m_nArrayWidth+j+1);
- // reverse because radiant uses CULL_FRONT
- //_mesh.indices[(j*_mesh.m_lenStrips)+i*2+1] = RenderIndex(((_mesh.m_nArrayHeight-1)-i)*_mesh.m_nArrayWidth+j);
- //_mesh.indices[(j*_mesh.m_lenStrips)+i*2] = RenderIndex(((_mesh.m_nArrayHeight-1)-i)*_mesh.m_nArrayWidth+j+1);
-
- }
- }
- }
-
- {
- PatchControlIter pCtrl = m_ctrlTransformed.begin();
- for(std::size_t j = 0, offStartY = 0; j+1 < m_height; j += 2, pCtrl += (strideU + strideV))
- {
- // set up array offsets for this sub-patch
- const bool leafY = (m_patchDef3) ? false : _mesh.curveTreeV[j>>1]->isLeaf();
- const std::size_t offMidY = (m_patchDef3) ? 0 : _mesh.curveTreeV[j>>1]->index;
- const std::size_t widthY = _mesh.arrayHeight[j>>1] * _mesh.m_nArrayWidth;
- const std::size_t offEndY = offStartY + widthY;
-
- for(std::size_t i = 0, offStartX = 0; i+1 < m_width; i += 2, pCtrl += (strideU << 1))
- {
- const bool leafX = (m_patchDef3) ? false : _mesh.curveTreeU[i>>1]->isLeaf();
- const std::size_t offMidX = (m_patchDef3) ? 0 : _mesh.curveTreeU[i>>1]->index;
- const std::size_t widthX = _mesh.arrayWidth[i>>1];
- const std::size_t offEndX = offStartX + widthX;
-
- PatchControlIter subMatrix[3][3];
- subMatrix[0][0] = pCtrl;
- subMatrix[0][1] = subMatrix[0][0]+strideU;
- subMatrix[0][2] = subMatrix[0][1]+strideU;
- subMatrix[1][0] = subMatrix[0][0]+strideV;
- subMatrix[1][1] = subMatrix[1][0]+strideU;
- subMatrix[1][2] = subMatrix[1][1]+strideU;
- subMatrix[2][0] = subMatrix[1][0]+strideV;
- subMatrix[2][1] = subMatrix[2][0]+strideU;
- subMatrix[2][2] = subMatrix[2][1]+strideU;
-
- // assign on-patch control points to vertex array
- if(i == 0 && j == 0)
- {
- vertex_clear_normal(_mesh.vertices[offStartX + offStartY]);
- }
- vertex_assign_ctrl(_mesh.vertices[offStartX + offStartY], *subMatrix[0][0]);
- if(j == 0)
- {
- vertex_clear_normal(_mesh.vertices[offEndX + offStartY]);
- }
- vertex_assign_ctrl(_mesh.vertices[offEndX + offStartY], *subMatrix[0][2]);
- if(i == 0)
- {
- vertex_clear_normal(_mesh.vertices[offStartX + offEndY]);
- }
- vertex_assign_ctrl(_mesh.vertices[offStartX + offEndY], *subMatrix[2][0]);
-
- vertex_clear_normal(_mesh.vertices[offEndX + offEndY]);
- vertex_assign_ctrl(_mesh.vertices[offEndX + offEndY], *subMatrix[2][2]);
-
- if(!m_patchDef3)
- {
- // assign remaining control points to vertex array
- if(!leafX)
- {
- vertex_assign_ctrl(_mesh.vertices[offMidX + offStartY], *subMatrix[0][1]);
- vertex_assign_ctrl(_mesh.vertices[offMidX + offEndY], *subMatrix[2][1]);
- }
- if(!leafY)
- {
- vertex_assign_ctrl(_mesh.vertices[offStartX + offMidY], *subMatrix[1][0]);
- vertex_assign_ctrl(_mesh.vertices[offEndX + offMidY], *subMatrix[1][2]);
-
- if(!leafX)
- {
- vertex_assign_ctrl(_mesh.vertices[offMidX + offMidY], *subMatrix[1][1]);
- }
- }
- }
-
- // test all 12 edges for degeneracy
- unsigned int nFlagsX = subarray_get_degen(pCtrl, strideU, strideV);
- unsigned int nFlagsY = subarray_get_degen(pCtrl, strideV, strideU);
- Vector3 tangentX[6], tangentY[6];
- Vector2 tangentS[6], tangentT[6];
-
- // set up tangents for each of the 12 edges if they were not degenerate
- if(!(nFlagsX & DEGEN_0a))
- {
- tangentX[0] = subMatrix[0][1]->vertex - subMatrix[0][0]->vertex;
- tangentS[0] = subMatrix[0][1]->texcoord - subMatrix[0][0]->texcoord;
- }
- if(!(nFlagsX & DEGEN_0b))
- {
- tangentX[1] = subMatrix[0][2]->vertex - subMatrix[0][1]->vertex;
- tangentS[1] = subMatrix[0][2]->texcoord - subMatrix[0][1]->texcoord;
- }
- if(!(nFlagsX & DEGEN_1a))
- {
- tangentX[2] = subMatrix[1][1]->vertex - subMatrix[1][0]->vertex;
- tangentS[2] = subMatrix[1][1]->texcoord - subMatrix[1][0]->texcoord;
- }
- if(!(nFlagsX & DEGEN_1b))
- {
- tangentX[3] = subMatrix[1][2]->vertex - subMatrix[1][1]->vertex;
- tangentS[3] = subMatrix[1][2]->texcoord - subMatrix[1][1]->texcoord;
- }
- if(!(nFlagsX & DEGEN_2a))
- {
- tangentX[4] = subMatrix[2][1]->vertex - subMatrix[2][0]->vertex;
- tangentS[4] = subMatrix[2][1]->texcoord - subMatrix[2][0]->texcoord;
- }
- if(!(nFlagsX & DEGEN_2b))
- {
- tangentX[5] = subMatrix[2][2]->vertex - subMatrix[2][1]->vertex;
- tangentS[5] = subMatrix[2][2]->texcoord - subMatrix[2][1]->texcoord;
- }
-
- if(!(nFlagsY & DEGEN_0a))
- {
- tangentY[0] = subMatrix[1][0]->vertex - subMatrix[0][0]->vertex;
- tangentT[0] = subMatrix[1][0]->texcoord - subMatrix[0][0]->texcoord;
- }
- if(!(nFlagsY & DEGEN_0b))
- {
- tangentY[1] = subMatrix[2][0]->vertex - subMatrix[1][0]->vertex;
- tangentT[1] = subMatrix[2][0]->texcoord - subMatrix[1][0]->texcoord;
- }
- if(!(nFlagsY & DEGEN_1a))
- {
- tangentY[2] = subMatrix[1][1]->vertex - subMatrix[0][1]->vertex;
- tangentT[2] = subMatrix[1][1]->texcoord - subMatrix[0][1]->texcoord;
- }
- if(!(nFlagsY & DEGEN_1b))
- {
- tangentY[3] = subMatrix[2][1]->vertex - subMatrix[1][1]->vertex;
- tangentT[3] = subMatrix[2][1]->texcoord - subMatrix[1][1]->texcoord;
- }
- if(!(nFlagsY & DEGEN_2a))
- {
- tangentY[4] = subMatrix[1][2]->vertex - subMatrix[0][2]->vertex;
- tangentT[4] = subMatrix[1][2]->texcoord - subMatrix[0][2]->texcoord;
- }
- if(!(nFlagsY & DEGEN_2b))
- {
- tangentY[5] = subMatrix[2][2]->vertex - subMatrix[1][2]->vertex;
- tangentT[5] = subMatrix[2][2]->texcoord - subMatrix[1][2]->texcoord;
- }
-
- // set up remaining edge tangents by borrowing the tangent from the closest parallel non-degenerate edge
- tangents_remove_degenerate(tangentX, tangentS, nFlagsX);
- tangents_remove_degenerate(tangentY, tangentT, nFlagsY);
-
- {
- // x=0, y=0
- std::size_t index = offStartX + offStartY;
- std::size_t index0 = 0;
- std::size_t index1 = 0;
-
- double dot = tangentX[index0].dot(tangentY[index1]);
- double length = tangentX[index0].getLength() * tangentY[index1].getLength();
-
- bestTangents00(nFlagsX, dot, length, index0, index1);
-
- accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
- }
-
- {
- // x=1, y=0
- std::size_t index = offEndX + offStartY;
- std::size_t index0 = 1;
- std::size_t index1 = 4;
-
- double dot = tangentX[index0].dot(tangentY[index1]);
- double length = tangentX[index0].getLength() * tangentY[index1].getLength();
-
- bestTangents10(nFlagsX, dot, length, index0, index1);
-
- accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
- }
-
- {
- // x=0, y=1
- std::size_t index = offStartX + offEndY;
- std::size_t index0 = 4;
- std::size_t index1 = 1;
-
- double dot = tangentX[index0].dot(tangentY[index1]);
- double length = tangentX[index1].getLength() * tangentY[index1].getLength();
-
- bestTangents01(nFlagsX, dot, length, index0, index1);
-
- accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
- }
-
- {
- // x=1, y=1
- std::size_t index = offEndX + offEndY;
- std::size_t index0 = 5;
- std::size_t index1 = 5;
-
- double dot = tangentX[index0].dot(tangentY[index1]);
- double length = tangentX[index0].getLength() * tangentY[index1].getLength();
-
- bestTangents11(nFlagsX, dot, length, index0, index1);
-
- accumulateVertexTangentSpace(index, tangentX, tangentY, tangentS, tangentT, index0, index1);
- }
-
- //normalise normals that won't be accumulated again
- if(i!=0 || j!=0)
- {
- normalise_safe(_mesh.vertices[offStartX + offStartY].normal);
- normalise_safe(_mesh.vertices[offStartX + offStartY].tangent);
- normalise_safe(_mesh.vertices[offStartX + offStartY].bitangent);
- }
- if(i+3 == m_width)
- {
- normalise_safe(_mesh.vertices[offEndX + offStartY].normal);
- normalise_safe(_mesh.vertices[offEndX + offStartY].tangent);
- normalise_safe(_mesh.vertices[offEndX + offStartY].bitangent);
- }
- if(j+3 == m_height)
- {
- normalise_safe(_mesh.vertices[offStartX + offEndY].normal);
- normalise_safe(_mesh.vertices[offStartX + offEndY].tangent);
- normalise_safe(_mesh.vertices[offStartX + offEndY].bitangent);
- }
- if(i+3 == m_width && j+3 == m_height)
- {
- normalise_safe(_mesh.vertices[offEndX + offEndY].normal);
- normalise_safe(_mesh.vertices[offEndX + offEndY].tangent);
- normalise_safe(_mesh.vertices[offEndX + offEndY].bitangent);
- }
-
- // set flags to average normals between shared edges
- if(j != 0)
- {
- nFlagsX |= AVERAGE;
- }
- if(i != 0)
- {
- nFlagsY |= AVERAGE;
- }
- // set flags to save evaluating shared edges twice
- nFlagsX |= SPLIT;
- nFlagsY |= SPLIT;
-
- // if the patch is curved.. tesselate recursively
- // use the relevant control curves for this sub-patch
- if(m_patchDef3)
- {
- TesselateSubMatrixFixed(&_mesh.vertices[offStartX + offStartY], 1, _mesh.m_nArrayWidth, nFlagsX, nFlagsY, subMatrix);
- }
- else
- {
- if(!leafX)
- {
- TesselateSubMatrix( _mesh.curveTreeU[i>>1], _mesh.curveTreeV[j>>1],
- offStartX, offStartY, offEndX, offEndY, // array offsets
- nFlagsX, nFlagsY,
- subMatrix[1][0]->vertex, subMatrix[1][1]->vertex, subMatrix[1][2]->vertex,
- subMatrix[1][0]->texcoord, subMatrix[1][1]->texcoord, subMatrix[1][2]->texcoord,
- false );
- }
- else if(!leafY)
- {
- TesselateSubMatrix( _mesh.curveTreeV[j>>1], _mesh.curveTreeU[i>>1],
- offStartY, offStartX, offEndY, offEndX, // array offsets
- nFlagsY, nFlagsX,
- subMatrix[0][1]->vertex, subMatrix[1][1]->vertex, subMatrix[2][1]->vertex,
- subMatrix[0][1]->texcoord, subMatrix[1][1]->texcoord, subMatrix[2][1]->texcoord,
- true );
- }
- }
-
- offStartX = offEndX;
- }
- offStartY = offEndY;
- }
- }
-}
-
-Vector3 getAverageNormal(const Vector3& normal1, const Vector3& normal2, double thickness)
-{
- // Beware of normals with 0 length
- if (normal1.getLengthSquared() == 0) return normal2;
- if (normal2.getLengthSquared() == 0) return normal1;
-
- // Both normals have length > 0
- Vector3 n1 = normal1.getNormalised();
- Vector3 n2 = normal2.getNormalised();
-
- // Get the angle bisector
- Vector3 normal = (n1 + n2).getNormalised();
-
- // Now calculate the length correction out of the angle
- // of the two normals
- float factor = cos(n1.angle(n2) * 0.5);
-
- // Stretch the normal to fit the required thickness
- normal *= thickness;
-
- // Check for div by zero (if the normals are antiparallel)
- // and stretch the resulting normal, if necessary
- if (factor != 0)
- {
- normal /= factor;
- }
-
- return normal;
-}
-
-void Patch::createThickenedOpposite(const Patch& sourcePatch,
- const float thickness,
- const int axis)
-{
- // Clone the dimensions from the other patch
- setDims(sourcePatch.getWidth(), sourcePatch.getHeight());
-
- // Also inherit the tesselation from the source patch
- setFixedSubdivisions(sourcePatch.subdivionsFixed(), sourcePatch.getSubdivisions());
-
- // Copy the shader from the source patch
- setShader(sourcePatch.getShader());
-
- // if extrudeAxis == 0,0,0 the patch is extruded along its vertex normals
- Vector3 extrudeAxis(0,0,0);
-
- switch (axis) {
- case 0: // X-Axis
- extrudeAxis = Vector3(1,0,0);
- break;
- case 1: // Y-Axis
- extrudeAxis = Vector3(0,1,0);
- break;
- case 2: // Z-Axis
- extrudeAxis = Vector3(0,0,1);
- break;
- default:
- // Default value already set during initialisation
- break;
- }
-
- for (std::size_t col = 0; col < m_width; col++)
- {
- for (std::size_t row = 0; row < m_height; row++)
- {
- // The current control vertex on the other patch
- const PatchControl& curCtrl = sourcePatch.ctrlAt(row, col);
-
- Vector3 normal;
-
- // Are we extruding along vertex normals (i.e. extrudeAxis == 0,0,0)?
- if (extrudeAxis == Vector3(0,0,0))
- {
- // The col tangents (empty if 0,0,0)
- Vector3 colTangent[2] = { Vector3(0,0,0), Vector3(0,0,0) };
-
- // Are we at the beginning/end of the column?
- if (col == 0 || col == m_width - 1)
- {
- // Get the next row index
- std::size_t nextCol = (col == m_width - 1) ? (col - 1) : (col + 1);
-
- const PatchControl& colNeighbour = sourcePatch.ctrlAt(row, nextCol);
-
- // One available tangent
- colTangent[0] = colNeighbour.vertex - curCtrl.vertex;
- // Reverse it if we're at the end of the column
- colTangent[0] *= (col == m_width - 1) ? -1 : +1;
- }
- // We are in between, two tangents can be calculated
- else
- {
- // Take two neighbouring vertices that should form a line segment
- const PatchControl& neighbour1 = sourcePatch.ctrlAt(row, col+1);
- const PatchControl& neighbour2 = sourcePatch.ctrlAt(row, col-1);
-
- // Calculate both available tangents
- colTangent[0] = neighbour1.vertex - curCtrl.vertex;
- colTangent[1] = neighbour2.vertex - curCtrl.vertex;
-
- // Reverse the second one
- colTangent[1] *= -1;
-
- // Cull redundant tangents
- if (colTangent[1].isParallel(colTangent[0]))
- {
- colTangent[1] = Vector3(0,0,0);
- }
- }
-
- // Calculate the tangent vectors to the next row
- Vector3 rowTangent[2] = { Vector3(0,0,0), Vector3(0,0,0) };
-
- // Are we at the beginning or the end?
- if (row == 0 || row == m_height - 1)
- {
- // Yes, only calculate one row tangent
- // Get the next row index
- std::size_t nextRow = (row == m_height - 1) ? (row - 1) : (row + 1);
-
- const PatchControl& rowNeighbour = sourcePatch.ctrlAt(nextRow, col);
-
- // First tangent
- rowTangent[0] = rowNeighbour.vertex - curCtrl.vertex;
- // Reverse it accordingly
- rowTangent[0] *= (row == m_height - 1) ? -1 : +1;
- }
- else
- {
- // Two tangents to calculate
- const PatchControl& rowNeighbour1 = sourcePatch.ctrlAt(row + 1, col);
- const PatchControl& rowNeighbour2 = sourcePatch.ctrlAt(row - 1, col);
-
- // First tangent
- rowTangent[0] = rowNeighbour1.vertex - curCtrl.vertex;
- rowTangent[1] = rowNeighbour2.vertex - curCtrl.vertex;
-
- // Reverse the second one
- rowTangent[1] *= -1;
-
- // Cull redundant tangents
- if (rowTangent[1].isParallel(rowTangent[0]))
- {
- rowTangent[1] = Vector3(0,0,0);
- }
- }
-
- // If two column tangents are available, take the length-corrected average
- if (colTangent[1].getLengthSquared() > 0)
- {
- // Two column normals to calculate
- Vector3 normal1 = rowTangent[0].crossProduct(colTangent[0]).getNormalised();
- Vector3 normal2 = rowTangent[0].crossProduct(colTangent[1]).getNormalised();
-
- normal = getAverageNormal(normal1, normal2, thickness);
-
- // Scale the normal down, as it is multiplied with thickness later on
- normal /= thickness;
- }
- else
- {
- // One column tangent available, maybe we have a second rowtangent?
- if (rowTangent[1].getLengthSquared() > 0)
- {
- // Two row normals to calculate
- Vector3 normal1 = rowTangent[0].crossProduct(colTangent[0]).getNormalised();
- Vector3 normal2 = rowTangent[1].crossProduct(colTangent[0]).getNormalised();
-
- normal = getAverageNormal(normal1, normal2, thickness);
-
- // Scale the normal down, as it is multiplied with thickness later on
- normal /= thickness;
- }
- else
- {
- normal = rowTangent[0].crossProduct(colTangent[0]).getNormalised();
- }
- }
- }
- else
- {
- // Take the predefined extrude direction instead
- normal = extrudeAxis;
- }
-
- // Store the new coordinates into this patch at the current coords
- ctrlAt(row, col).vertex = curCtrl.vertex + normal*thickness;
+ // Store the new coordinates into this patch at the current coords
+ ctrlAt(row, col).vertex = curCtrl.vertex + normal*thickness;
// Clone the texture cooordinates of the source patch
ctrlAt(row, col).texcoord = curCtrl.texcoord;
@@ -3888,7 +2493,7 @@ void Patch::createThickenedWall(const Patch& sourcePatch,
int sourceWidth = static_cast<int>(sourcePatch.getWidth());
int sourceHeight = static_cast<int>(sourcePatch.getHeight());
- bool sourceTesselationFixed = sourcePatch.subdivionsFixed();
+ bool sourceTesselationFixed = sourcePatch.subdivisionsFixed();
Subdivisions sourceTesselationX(sourcePatch.getSubdivisions().x(), 1);
Subdivisions sourceTesselationY(sourcePatch.getSubdivisions().y(), 1);
@@ -3959,8 +2564,8 @@ void Patch::stitchTextureFrom(Patch& sourcePatch) {
undoSave();
// Convert the size_t stuff into int, because we need it for signed comparisons
- int patchHeight = static_cast<int>(m_height);
- int patchWidth = static_cast<int>(m_width);
+ int patchHeight = static_cast<int>(_height);
+ int patchWidth = static_cast<int>(_width);
// Calculate the nearest corner vertex of this patch (to the sourcepatch vertices)
PatchControlIter nearestControl = getClosestPatchControlToPatch(sourcePatch);
@@ -3980,7 +2585,7 @@ void Patch::stitchTextureFrom(Patch& sourcePatch) {
// Now shift all the texture vertices in the right direction, so that this patch
// is getting as close as possible to the origin in texture space.
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
i->texcoord += shift;
}
@@ -4020,10 +2625,10 @@ void Patch::normaliseTexture() {
// Find the nearest control vertex
// Initialise the compare value
- PatchControlIter nearestControl = m_ctrl.begin();
+ PatchControlIter nearestControl = _ctrl.begin();
// Cycle through all the control points with an iterator
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
// Take the according value (e.g. s = x, t = y, depending on the nAxis argument)
// and apply the appropriate texture coordinate
if (i->texcoord.getLength() < nearestControl->texcoord.getLength()) {
@@ -4049,7 +2654,7 @@ void Patch::normaliseTexture() {
// Now shift all the texture vertices in the right direction, so that this patch
// is getting as close as possible to the origin in texture space.
- for (PatchControlIter i = m_ctrl.begin(); i != m_ctrl.end(); ++i) {
+ for (PatchControlIter i = _ctrl.begin(); i != _ctrl.end(); ++i) {
i->texcoord += shift;
}
@@ -4058,29 +2663,34 @@ void Patch::normaliseTexture() {
}
}
-Subdivisions Patch::getSubdivisions() const {
- return Subdivisions(m_subdivisions_x, m_subdivisions_y);
+const Subdivisions& Patch::getSubdivisions() const
+{
+ return _subDivisions;
}
-void Patch::setFixedSubdivisions(bool isFixed, const Subdivisions& divisions) {
+void Patch::setFixedSubdivisions(bool isFixed, const Subdivisions& divisions)
+{
undoSave();
- m_patchDef3 = isFixed;
- m_subdivisions_x = divisions.x();
- m_subdivisions_y = divisions.y();
+ _patchDef3 = isFixed;
+ _subDivisions = divisions;
- if (m_subdivisions_x == 0) {
- m_subdivisions_x = 4;
+ if (_subDivisions.x() == 0)
+ {
+ _subDivisions.x() = 4;
}
- else if (m_subdivisions_x > MAX_PATCH_SUBDIVISIONS) {
- m_subdivisions_x = MAX_PATCH_SUBDIVISIONS;
+ else if (_subDivisions.x() > MAX_PATCH_SUBDIVISIONS)
+ {
+ _subDivisions.x() = MAX_PATCH_SUBDIVISIONS;
}
- if (m_subdivisions_y == 0) {
- m_subdivisions_y = 4;
+ if (_subDivisions.y() == 0)
+ {
+ _subDivisions.y() = 4;
}
- else if (m_subdivisions_y > MAX_PATCH_SUBDIVISIONS) {
- m_subdivisions_y = MAX_PATCH_SUBDIVISIONS;
+ else if (_subDivisions.y() > MAX_PATCH_SUBDIVISIONS)
+ {
+ _subDivisions.y() = MAX_PATCH_SUBDIVISIONS;
}
SceneChangeNotify();
@@ -4088,8 +2698,9 @@ void Patch::setFixedSubdivisions(bool isFixed, const Subdivisions& divisions) {
controlPointsChanged();
}
-bool Patch::subdivionsFixed() const {
- return m_patchDef3;
+bool Patch::subdivisionsFixed() const
+{
+ return _patchDef3;
}
bool Patch::getIntersection(const Ray& ray, Vector3& intersection)
@@ -4097,11 +2708,11 @@ bool Patch::getIntersection(const Ray& ray, Vector3& intersection)
std::vector<RenderIndex>::const_iterator stripStartIndex = _mesh.indices.begin();
// Go over each quad strip and intersect the ray with its triangles
- for (std::size_t strip = 0; strip < _mesh.m_numStrips; ++strip)
+ for (std::size_t strip = 0; strip < _mesh.numStrips; ++strip)
{
// Iterate over the indices. The +2 increment will lead up to the next quad
for (std::vector<RenderIndex>::const_iterator indexIter = stripStartIndex;
- indexIter + 2 < stripStartIndex + _mesh.m_lenStrips; indexIter += 2)
+ indexIter + 2 < stripStartIndex + _mesh.lenStrips; indexIter += 2)
{
Vector3 triangleIntersection;
@@ -4131,7 +2742,7 @@ bool Patch::getIntersection(const Ray& ray, Vector3& intersection)
}
}
- stripStartIndex += _mesh.m_lenStrips;
+ stripStartIndex += _mesh.lenStrips;
}
return false;
diff --git a/radiant/patch/Patch.h b/radiant/patch/Patch.h
index c79bd8a..24cb36b 100644
--- a/radiant/patch/Patch.h
+++ b/radiant/patch/Patch.h
@@ -18,6 +18,9 @@
#include "brush/FacePlane.h"
#include "brush/Face.h"
+// Enable to render the vertex normal/tangent/bitangent vectors in the cam view
+#define DEBUG_PATCH_NTB_VECTORS 0
+
class PatchNode;
class Ray;
@@ -38,18 +41,18 @@ class Patch :
typedef std::set<IPatch::Observer*> Observers;
Observers _observers;
- AABB m_aabb_local; // local bbox
+ AABB _localAABB; // local bbox
// Patch dimensions
- std::size_t m_width;
- std::size_t m_height;
+ std::size_t _width;
+ std::size_t _height;
IUndoStateSaver* _undoStateSaver;
- // dynamically allocated array of control points, size is m_width*m_height
- PatchControlArray m_ctrl; // the true control array
- PatchControlArray m_ctrlTransformed; // a temporary control array used during transformations, so that the
- // changes can be reverted and overwritten by <m_ctrl>
+ // dynamically allocated array of control points, size is _width*_height
+ PatchControlArray _ctrl; // the true control array
+ PatchControlArray _ctrlTransformed; // a temporary control array used during transformations, so that the
+ // changes can be reverted and overwritten by <_ctrl>
// The tesselation for this patch
PatchTesselation _mesh;
@@ -58,60 +61,54 @@ class Patch :
RenderablePatchSolid _solidRenderable;
RenderablePatchWireframe _wireframeRenderable;
RenderablePatchFixedWireframe _fixedWireframeRenderable;
+ RenderablePatchVectorsNTB _renderableNTBVectors;
// The shader states for the control points and the lattice
ShaderPtr _pointShader;
ShaderPtr _latticeShader;
// greebo: The vertex list of the control points, can be passed to the RenderableVertexBuffer
- std::vector<VertexCb> m_ctrl_vertices;
+ std::vector<VertexCb> _ctrl_vertices;
// The renderable of the control points
RenderableVertexBuffer _renderableCtrlPoints;
// The lattice indices and their renderable
- IndexBuffer m_lattice_indices;
+ IndexBuffer _latticeIndices;
RenderableIndexBuffer _renderableLattice;
- bool m_bOverlay;
-
- bool m_transformChanged;
+ bool _transformChanged;
// TRUE if the patch tesselation needs an update
bool _tesselationChanged;
- // Callback functions when the patch gets changed
- Callback m_evaluateTransform;
-
// The rendersystem we're attached to, to acquire materials
RenderSystemWeakPtr _renderSystem;
// Shader container, taking care of use count
SurfaceShader _shader;
+ // If true, this patch is using fixed subdivisions
+ bool _patchDef3;
+
+ // Fixed subdivision layout of this patch
+ Subdivisions _subDivisions;
+
// greebo: Initialises the patch member variables
void construct();
public:
- bool m_patchDef3;
- // The number of subdivisions of this patch
- std::size_t m_subdivisions_x;
- std::size_t m_subdivisions_y;
-
-public:
- static int m_CycleCapIndex;// = 0;
-
// Constructor
- Patch(PatchNode& node, const Callback& evaluateTransform);
+ Patch(PatchNode& node);
// Copy constructors (create this patch from another patch)
- Patch(const Patch& other, PatchNode& node, const Callback& evaluateTransform);
+ Patch(const Patch& other, PatchNode& node);
~Patch();
PatchNode& getPatchNode();
- void attachObserver(Observer* observer);
- void detachObserver(Observer* observer);
+ void attachObserver(Observer* observer) override;
+ void detachObserver(Observer* observer) override;
void connectUndoSystem(IMapFileChangeTracker& changeTracker);
void disconnectUndoSystem(IMapFileChangeTracker& changeTracker);
@@ -157,51 +154,51 @@ public:
void freezeTransform();
// callback for changed control points
- void controlPointsChanged();
+ void controlPointsChanged() override;
// Check if the patch has invalid control points or width/height are zero
- bool isValid() const;
+ bool isValid() const override;
// Check whether all control vertices are in the same 3D spot (with minimal tolerance)
- bool isDegenerate() const;
+ bool isDegenerate() const override;
// Snaps the control points to the grid
void snapto(float snap);
// Gets the shader name or sets the shader to <name>
- const std::string& getShader() const;
- void setShader(const std::string& name);
+ const std::string& getShader() const override;
+ void setShader(const std::string& name) override;
const SurfaceShader& getSurfaceShader() const;
SurfaceShader& getSurfaceShader();
// greebo: returns true if the patch's shader is visible, false otherwise
- bool hasVisibleMaterial() const;
+ bool hasVisibleMaterial() const override;
// As the name states: get the shader flags of the m_state shader
int getShaderFlags() const;
// Const and non-const iterators
PatchControlIter begin() {
- return m_ctrl.begin();
+ return _ctrl.begin();
}
PatchControlConstIter begin() const {
- return m_ctrl.begin();
+ return _ctrl.begin();
}
PatchControlIter end() {
- return m_ctrl.end();
+ return _ctrl.end();
}
PatchControlConstIter end() const {
- return m_ctrl.end();
+ return _ctrl.end();
}
PatchTesselation& getTesselation();
// Returns a copy of the tesselated geometry
- PatchMesh getTesselatedPatchMesh() const;
+ PatchMesh getTesselatedPatchMesh() const override;
// Get the current control point array
PatchControlArray& getControlPoints();
@@ -211,35 +208,35 @@ public:
const PatchControlArray& getControlPointsTransformed() const;
// Set the dimensions of this patch to width <w>, height <h>
- void setDims(std::size_t w, std::size_t h);
+ void setDims(std::size_t w, std::size_t h) override;
// Get the patch dimensions
- std::size_t getWidth() const;
- std::size_t getHeight() const;
+ std::size_t getWidth() const override;
+ std::size_t getHeight() const override;
// Return a defined patch control vertex at <row>,<col>
- PatchControl& ctrlAt(std::size_t row, std::size_t col);
+ PatchControl& ctrlAt(std::size_t row, std::size_t col) override;
// The same as above just for const
- const PatchControl& ctrlAt(std::size_t row, std::size_t col) const;
+ const PatchControl& ctrlAt(std::size_t row, std::size_t col) const override;
/** greebo: Inserts two columns before and after the column with index <colIndex>.
* Throws an GenericPatchException if an error occurs.
*/
- void insertColumns(std::size_t colIndex);
+ void insertColumns(std::size_t colIndex) override;
/** greebo: Inserts two rows before and after the row with index <rowIndex>.
* Throws an GenericPatchException if an error occurs.
*/
- void insertRows(std::size_t rowIndex);
+ void insertRows(std::size_t rowIndex) override;
/** greebo: Removes columns or rows right before and after the col/row
* with the given index, reducing the according dimension by 2.
*/
- void removePoints(bool columns, std::size_t index);
+ void removePoints(bool columns, std::size_t index) override;
/** greebo: Appends two rows or columns at the beginning or the end.
*/
- void appendPoints(bool columns, bool beginning);
+ void appendPoints(bool columns, bool beginning) override;
void ConstructPrefab(const AABB& aabb, EPatchPrefab eType, EViewType viewType, std::size_t width = 3, std::size_t height = 3);
void constructPlane(const AABB& aabb, int axis, std::size_t width, std::size_t height);
@@ -278,7 +275,6 @@ public:
void SetTextureRepeat(float s, float t); // call with s=1 t=1 for FIT
void CapTexture();
void NaturalTexture();
- void ProjectTexture(int nAxis);
// Aligns the patch texture along the given side/border - if possible
void alignTexture(EAlignType align);
@@ -340,20 +336,20 @@ public:
// Revert the state of this patch to the one that has been saved in the UndoMemento
void importState(const IUndoMementoPtr& state);
- /** greebo: Sets/gets whether this patch is a patchDef3 (fixed tesselation)
+ /** greebo: Gets whether this patch is a patchDef3 (fixed tesselation)
*/
- bool subdivionsFixed() const;
+ bool subdivisionsFixed() const override;
/** greebo: Returns the x,y subdivision values (for tesselation)
*/
- Subdivisions getSubdivisions() const;
+ const Subdivisions& getSubdivisions() const override;
/** greebo: Sets the subdivision of this patch
*
* @isFixed: TRUE, if this patch should be a patchDef3 (fixed tesselation)
* @divisions: a two-component vector containing the desired subdivisions
*/
- void setFixedSubdivisions(bool isFixed, const Subdivisions& divisions);
+ void setFixedSubdivisions(bool isFixed, const Subdivisions& divisions) override;
// Calculate the intersection of the given ray with the full patch mesh,
// returns true on intersection and fills in the out variable
@@ -369,23 +365,4 @@ private:
void check_shader();
void updateAABB();
-
- void TesselateSubMatrixFixed(ArbitraryMeshVertex* vertices,
- std::size_t strideX, std::size_t strideY,
- unsigned int nFlagsX, unsigned int nFlagsY,
- PatchControlIter subMatrix[3][3]);
-
- // uses binary trees representing bezier curves to recursively tesselate a bezier sub-patch
- void TesselateSubMatrix( const BezierCurveTree *BX, const BezierCurveTree *BY,
- std::size_t offStartX, std::size_t offStartY,
- std::size_t offEndX, std::size_t offEndY,
- std::size_t nFlagsX, std::size_t nFlagsY,
- Vector3& left, Vector3& mid, Vector3& right,
- Vector2& texLeft, Vector2& texMid, Vector2& texRight,
- bool bTranspose );
-
- // tesselates the entire surface
- void BuildTesselationCurves(EMatrixMajor major);
- void accumulateVertexTangentSpace(std::size_t index, Vector3 tangentX[6], Vector3 tangentY[6], Vector2 tangentS[6], Vector2 tangentT[6], std::size_t index0, std::size_t index1);
- void BuildVertexArray();
};
diff --git a/radiant/patch/PatchBezier.cpp b/radiant/patch/PatchBezier.cpp
deleted file mode 100644
index 651aefe..0000000
--- a/radiant/patch/PatchBezier.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-#include "PatchBezier.h"
-
-#include "math/pi.h"
-#include "registry/registry.h"
-
- namespace {
- const std::string RKEY_PATCH_SUBDIVIDE_THRESHOLD = "user/ui/patch/subdivideThreshold";
- }
-
-/* greebo: These are a lot of helper functions related to bezier curves
- */
-
-void BezierInterpolate(BezierCurve *pCurve) {
- pCurve->left = pCurve->left.mid(pCurve->crd);
- pCurve->right = pCurve->crd.mid(pCurve->right);
- pCurve->crd = pCurve->left.mid(pCurve->right);
-}
-
-bool BezierCurve::isCurved() const
-{
- // Calculate the deltas
- Vector3 vTemp(right - left);
- Vector3 v1(crd - left);
-
- if (v1 == g_vector3_identity || vTemp == v1) // return 0 if 1->2 == 0 or 1->2 == 1->3
- {
- return false;
- }
-
- Vector3 v2(right - crd);
-
- v1.normalise();
- v2.normalise();
-
- if (v1 == v2)
- {
- // All points are on the same line
- return false;
- }
-
- Vector3 v3(vTemp);
- const double width = v3.getLength();
-
- v3 *= 1.0 / width;
-
- if (v1 == v3 && v2 == v3)
- {
- return false;
- }
-
- // The points are not on the same line, determine the angle
- const double angle = acos(v1.dot(v2)) / c_pi;
-
- const double index = width * angle;
-
- static float subdivideThreshold = registry::getValue<float>(RKEY_PATCH_SUBDIVIDE_THRESHOLD);
-
- if (index > subdivideThreshold)
- {
- return true;
- }
-
- return false;
-}
-
-/**
- * greebo: The vertex interpolation works like this:
- *
- * The original segment is LEFT >> CRD >> RIGHT, which will be sudivided into two segments: "left" and "right".
- *
- * The "left" segment will be LEFT >> ip_left >> ip_crd
- * The "right" segment will be ip_crd >> ip_right >> RIGHT
- *
- * In the end, the two segments will still be using the LEFT and RIGHT vertices (which is important as these are the
- * "fixed" control points of the patch, but the CRD one will be disregarded.
-
- LEFT O
- |
- |
- |
- |
- |
- |
-ip_left X
- |\
- | \
- | \
- | X ip_crd
- | \
- | \
- CRD O------X------O RIGHT
- ip_right
-*/
-void BezierCurve::interpolate(BezierCurve* leftCurve, BezierCurve* rightCurve) const
-{
- // The left and right vertices are the anchors
- leftCurve->left = left;
- rightCurve->right = right;
-
- // The mid-point of the current curve
- leftCurve->crd = left.mid(crd); // ip_left
- rightCurve->crd = crd.mid(right); // ip_right
- leftCurve->right = rightCurve->left = leftCurve->crd.mid(rightCurve->crd); // ip_crd
-}
-
-std::size_t BezierCurveTree::setup(std::size_t idx, std::size_t stride)
-{
- if (left != NULL && right != NULL)
- {
- idx = left->setup(idx, stride);
-
- // Store new index
- index = idx*stride;
-
- idx++;
- idx = right->setup(idx, stride);
- }
- else
- {
- // Either left or right is NULL, assign leaf index
- index = BEZIERCURVETREE_MAX_INDEX;
- }
-
- // idx will be returned unchanged if no children have been setup
- return idx;
-}
-
-const std::size_t PATCH_MAX_SUBDIVISION_DEPTH = 16;
-
-void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, BezierCurveList& curveList, std::size_t depth)
-{
- BezierCurveList leftList;
- BezierCurveList rightList;
-
- bool listSplit = false;
-
- // Traverse the list and interpolate all curves which satisfy the "isCurved" condition
- for (BezierCurveList::iterator l = curveList.begin(); l != curveList.end(); ++l)
- {
- BezierCurve* curve = *l;
-
- if (listSplit || curve->isCurved())
- {
- // Set the flag to TRUE to indicate that we already subdivided one part of this list
- // All other parts will be subdivided too
- listSplit = true;
-
- // Split this curve in two, by allocating two new curves
- BezierCurve* leftCurve = new BezierCurve;
- BezierCurve* rightCurve = new BezierCurve;
-
- // Let the current curve submit interpolation data to the newly allocated curves
- curve->interpolate(leftCurve, rightCurve);
-
- // Add the new curves to the allocated list
- leftList.push_front(leftCurve);
- rightList.push_front(rightCurve);
- }
- }
-
- // If we have a subdivision in this list, enter to the next level of recursion
- if (!leftList.empty() && !rightList.empty() && depth != PATCH_MAX_SUBDIVISION_DEPTH)
- {
- // Allocate two new tree nodes for the left and right part
- pTree->left = new BezierCurveTree;
- pTree->right = new BezierCurveTree;
-
- BezierCurveTree_FromCurveList(pTree->left, leftList, depth + 1);
- BezierCurveTree_FromCurveList(pTree->right, rightList, depth + 1);
-
- // Free the left and right lists from this level recursion
- std::for_each(leftList.begin(), leftList.end(), [] (BezierCurve* curve)
- {
- delete curve;
- });
-
- std::for_each(rightList.begin(), rightList.end(), [] (BezierCurve* curve)
- {
- delete curve;
- });
- }
-
- // If no subdivisions have been calculated, just leave this tree node, children are NULL by default
-}
diff --git a/radiant/patch/PatchBezier.h b/radiant/patch/PatchBezier.h
deleted file mode 100644
index 6978191..0000000
--- a/radiant/patch/PatchBezier.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#pragma once
-
-#include "math/Vector3.h"
-#include <limits>
-#include <vector>
-#include <forward_list>
-
-struct BezierCurve
-{
- Vector3 crd;
- Vector3 left;
- Vector3 right;
-
- BezierCurve()
- {}
-
- BezierCurve(const Vector3& crd_, const Vector3& left_, const Vector3& right_) :
- crd(crd_),
- left(left_),
- right(right_)
- {}
-
- // Returns true if the given set of coordinates satisfies the "curved" condition
- // This is determined by comparing the directions of the various deltas
- bool isCurved() const;
-
- // Interpolates the curve values and writes them to <leftCurve> and <rightCurve>
- // which will form two new (connected) segments interpolating the current one.
- void interpolate(BezierCurve* leftCurve, BezierCurve* rightCurve) const;
-};
-
-const std::size_t BEZIERCURVETREE_MAX_INDEX = std::numeric_limits<std::size_t>::max();
-
-/**
- * greebo: A BezierCurveTree represents a node in the binary subdivision tree.
- * If left and right are both NULL, this node is a leaf and no further subdivisions
- * are available for this part of the patch. The index variable holds the depth of this node.
- * A leaf carries BEZIERCURVETREE_MAX_INDEX as index.
- */
-class BezierCurveTree
-{
-public:
- std::size_t index;
- BezierCurveTree* left;
- BezierCurveTree* right;
-
- BezierCurveTree() :
- left(NULL),
- right(NULL)
- {}
-
- ~BezierCurveTree()
- {
- delete left; // it's safe to pass NULL to delete
- delete right;
- }
-
- // Returns TRUE when no more subdivisions are available beyond this depth
- bool isLeaf() const
- {
- return left == NULL && right == NULL;
- }
-
- // Sets up the indices of this part of the curve tree
- // Recursively calls setup() on the children if available
- // The index is returned unchanged if no children are set up.
- std::size_t setup(std::size_t idx, std::size_t stride);
-};
-
-typedef std::forward_list<BezierCurve*> BezierCurveList;
-
-void BezierCurveTree_FromCurveList(BezierCurveTree *pTree, BezierCurveList& curveList, std::size_t depth = 0);
-
-void BezierInterpolate(BezierCurve *pCurve);
-
-inline void BezierCurveTreeArray_deleteAll(std::vector<BezierCurveTree*>& curveTrees) {
- for(std::vector<BezierCurveTree*>::iterator i = curveTrees.begin(); i != curveTrees.end(); ++i) {
- delete *i;
- }
-}
diff --git a/radiant/patch/PatchCreators.cpp b/radiant/patch/PatchCreators.cpp
index 3407c24..08fd8f5 100644
--- a/radiant/patch/PatchCreators.cpp
+++ b/radiant/patch/PatchCreators.cpp
@@ -59,8 +59,8 @@ void Doom3PatchCreator::initialiseModule(const ApplicationContext& ctx)
registerPatchCommands();
// Construct and Register the patch-related preferences
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Patch"));
- page->appendEntry(_("Patch Subdivide Threshold"), RKEY_PATCH_SUBDIVIDE_THRESHOLD);
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Patch"));
+ page.appendEntry(_("Patch Subdivide Threshold"), RKEY_PATCH_SUBDIVIDE_THRESHOLD);
}
void Doom3PatchCreator::registerPatchCommands()
@@ -92,7 +92,6 @@ void Doom3PatchCreator::registerPatchCommands()
GlobalCommandSystem().addCommand("RedisperseCols", selection::algorithm::redispersePatchCols);
GlobalCommandSystem().addCommand("MatrixTranspose", selection::algorithm::transposePatch);
GlobalCommandSystem().addCommand("CapCurrentCurve", selection::algorithm::capPatch);
- GlobalCommandSystem().addCommand("CycleCapTexturePatch", selection::algorithm::cyclePatchProjection);
GlobalCommandSystem().addCommand("ThickenPatch", selection::algorithm::thickenPatches);
GlobalCommandSystem().addCommand("StitchPatchTexture", patch::algorithm::stitchTextures);
GlobalCommandSystem().addCommand("BulgePatch", patch::algorithm::bulge);
diff --git a/radiant/patch/PatchModule.cpp b/radiant/patch/PatchModule.cpp
index 3f0f83d..ac96167 100644
--- a/radiant/patch/PatchModule.cpp
+++ b/radiant/patch/PatchModule.cpp
@@ -1,45 +1,6 @@
-/*
-Copyright (C) 2001-2006, William Joseph.
-All Rights Reserved.
-
-This file is part of GtkRadiant.
-
-GtkRadiant is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-GtkRadiant 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 General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-#include "iradiant.h"
-#include "ipatch.h"
-#include "ifilter.h"
-#include "ipreferencesystem.h"
-
-#include "PatchNode.h"
-#include "PatchSceneWalk.h"
#include "PatchCreators.h"
-
#include "modulesystem/StaticModule.h"
-#include "modulesystem/ModuleRegistry.h"
// Define the static patchcreator modules
module::StaticModule<Doom3PatchCreator> doom3PatchDef3Creator;
module::StaticModule<Doom3PatchDef2Creator> doom3PatchDef2Creator;
-
-// These are the "host" functions containing the static instances of the patch creators.
-PatchCreator& GetDoom3PatchCreator() {
- return GlobalPatchCreator(DEF3);
-}
-
-PatchCreator& GetDoom3PatchDef2Creator() {
- return GlobalPatchCreator(DEF2);
-}
diff --git a/radiant/patch/PatchNode.cpp b/radiant/patch/PatchNode.cpp
index abf6737..ea21ebe 100644
--- a/radiant/patch/PatchNode.cpp
+++ b/radiant/patch/PatchNode.cpp
@@ -12,11 +12,10 @@ PatchNode::PatchNode(bool patchDef3) :
m_dragPlanes(std::bind(&PatchNode::selectedChangedComponent, this, std::placeholders::_1)),
m_render_selected(GL_POINTS),
m_lightList(&GlobalRenderSystem().attachLitObject(*this)),
- m_patch(*this,
- Callback(std::bind(&PatchNode::evaluateTransform, this))), // create the m_patch member with the node parameters
+ m_patch(*this),
_untransformedOriginChanged(true)
{
- m_patch.m_patchDef3 = patchDef3;
+ m_patch.setFixedSubdivisions(patchDef3, Subdivisions(m_patch.getSubdivisions()));
SelectableNode::setTransformChangedCallback(Callback(std::bind(&PatchNode::lightsChanged, this)));
}
@@ -37,9 +36,7 @@ PatchNode::PatchNode(const PatchNode& other) :
m_dragPlanes(std::bind(&PatchNode::selectedChangedComponent, this, std::placeholders::_1)),
m_render_selected(GL_POINTS),
m_lightList(&GlobalRenderSystem().attachLitObject(*this)),
- m_patch(other.m_patch,
- *this,
- Callback(std::bind(&PatchNode::evaluateTransform, this))), // create the patch out of the <other> one
+ m_patch(other.m_patch, *this), // create the patch out of the <other> one
_untransformedOriginChanged(true)
{
SelectableNode::setTransformChangedCallback(Callback(std::bind(&PatchNode::lightsChanged, this)));
@@ -175,6 +172,18 @@ void PatchNode::setSelectedComponents(bool select, SelectionSystem::EComponentMo
}
}
+void PatchNode::invertSelectedComponents(SelectionSystem::EComponentMode mode)
+{
+ if (mode == SelectionSystem::eVertex)
+ {
+ // Cycle through the transformed patch vertices and set the colour of all selected control vertices to BLUE (hardcoded)
+ for (PatchControlInstance& i : m_ctrl_instances)
+ {
+ i.setSelected(!i.isSelected());
+ }
+ }
+}
+
void PatchNode::testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) {
test.BeginMesh(localToWorld());
@@ -216,28 +225,7 @@ bool PatchNode::hasVisibleMaterial() const
return m_patch.getSurfaceShader().getGLShader()->getMaterial()->isVisible();
}
-void PatchNode::invertSelected()
-{
- // Override default behaviour of SelectableNode, we have components
-
- if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent)
- {
- // Cycle through the transformed patch vertices and set the colour of all selected control vertices to BLUE (hardcoded)
- PatchControlIter ctrl = m_patch.getControlPointsTransformed().begin();
-
- for (PatchControlInstances::iterator i = m_ctrl_instances.begin(); i != m_ctrl_instances.end(); ++i, ++ctrl)
- {
- i->invertSelected();
- }
- }
- else // primitive mode
- {
- // Invert the selection of the patch itself
- SelectableNode::invertSelected();
- }
-}
-
-void PatchNode::selectedChangedComponent(const Selectable& selectable) {
+void PatchNode::selectedChangedComponent(const ISelectable& selectable) {
// Notify the selection system that this PatchNode was selected. The RadiantSelectionSystem adds
// this to its internal list of selected nodes.
GlobalSelectionSystem().onComponentSelection(SelectableNode::getSelf(), selectable);
@@ -291,7 +279,7 @@ bool PatchNode::intersectsLight(const RendererLight& light) const {
void PatchNode::renderSolid(RenderableCollector& collector, const VolumeTest& volume) const
{
// Don't render invisible shaders
- if (!m_patch.hasVisibleMaterial()) return;
+ if (!isForcedVisible() && !m_patch.hasVisibleMaterial()) return;
const_cast<Patch&>(m_patch).evaluateTransform();
collector.setLights(*m_lightList);
@@ -308,7 +296,7 @@ void PatchNode::renderSolid(RenderableCollector& collector, const VolumeTest& vo
void PatchNode::renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const
{
// Don't render invisible shaders
- if (!m_patch.getSurfaceShader().getGLShader()->getMaterial()->isVisible()) return;
+ if (!isForcedVisible() && !m_patch.hasVisibleMaterial()) return;
const_cast<Patch&>(m_patch).evaluateTransform();
@@ -380,16 +368,18 @@ void PatchNode::renderComponentsSelected(RenderableCollector& collector, const V
// If there are any selected components, add them to the collector
if (!m_render_selected.empty())
{
- collector.highlightPrimitives(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
collector.SetState(PatchNode::m_state_selpoint, RenderableCollector::eWireframeOnly);
collector.SetState(PatchNode::m_state_selpoint, RenderableCollector::eFullMaterials);
collector.addRenderable(m_render_selected, localToWorld());
}
}
-bool PatchNode::isHighlighted() const
+std::size_t PatchNode::getHighlightFlags()
{
- return isSelected();
+ if (!isSelected()) return Highlight::NoHighlight;
+
+ return isGroupMember() ? (Highlight::Selected | Highlight::GroupMember) : Highlight::Selected;
}
void PatchNode::evaluateTransform()
diff --git a/radiant/patch/PatchNode.h b/radiant/patch/PatchNode.h
index a2aaa51..44bc88f 100644
--- a/radiant/patch/PatchNode.h
+++ b/radiant/patch/PatchNode.h
@@ -5,7 +5,7 @@
#include "itraceable.h"
#include "imap.h"
#include "Patch.h"
-#include "SelectableNode.h"
+#include "scene/SelectableNode.h"
#include "PatchControlInstance.h"
#include "dragplanes.h"
@@ -82,11 +82,13 @@ public:
void selectReversedPlanes(Selector& selector, const SelectedPlanes& selectedPlanes);
// Returns true if any of the patch components is selected
- bool isSelectedComponents() const;
+ bool isSelectedComponents() const override;
// Set the components (control points or dragplanes) selection to <select>
- void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode);
+ void setSelectedComponents(bool select, SelectionSystem::EComponentMode mode) override;
+ // Invert the component selection
+ void invertSelectedComponents(SelectionSystem::EComponentMode mode) override;
// Tests the patch components on selection using the passed SelectionTest
- void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode);
+ void testSelectComponents(Selector& selector, SelectionTest& test, SelectionSystem::EComponentMode mode) override;
// override scene::Inode::onRemoveFromScene to deselect the child components
virtual void onInsertIntoScene(scene::IMapRootNode& root) override;
@@ -116,12 +118,9 @@ public:
// Clones this node, allocates a new Node on the heap and passes itself to the constructor of the new node
scene::INodePtr clone() const;
- // Override ObservedSelectable behaviour
- virtual void invertSelected();
-
// greebo: This gets called by the ObservedSelectable as soon as its selection state changes
// (see ObservedSelectable and PatchControlInstance)
- void selectedChangedComponent(const Selectable& selectable);
+ void selectedChangedComponent(const ISelectable& selectable);
// LitObject implementation
bool intersectsLight(const RendererLight& light) const;
@@ -130,15 +129,15 @@ public:
// Render functions, these make sure that all things get rendered properly. The calls are also passed on
// to the contained patch <m_patch>
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
// Renders the components of this patch instance, makes use of the Patch::render_component() method
- void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderComponents(RenderableCollector& collector, const VolumeTest& volume) const override;
void evaluateTransform();
- bool isHighlighted() const;
+ std::size_t getHighlightFlags() override;
// Returns the center of the untransformed world AABB
const Vector3& getUntransformedOrigin() override;
diff --git a/radiant/patch/PatchRenderables.cpp b/radiant/patch/PatchRenderables.cpp
index affd00c..63aa68b 100644
--- a/radiant/patch/PatchRenderables.cpp
+++ b/radiant/patch/PatchRenderables.cpp
@@ -15,76 +15,6 @@ void RenderablePatchWireframe::render(const RenderInfo& info) const
{
_needsUpdate = false;
- const std::vector<ArbitraryMeshVertex>& patchVerts = _tess.vertices;
-
- // Vertex buffer to receive and render vertices
- VertexBuffer_T currentVBuf;
-
- std::size_t firstIndex = 0;
- for (std::size_t i = 0; i <= _tess.curveTreeV.size(); ++i)
- {
- currentVBuf.addBatch(patchVerts.begin() + firstIndex,
- _tess.m_nArrayWidth);
-
- if (i == _tess.curveTreeV.size()) break;
-
- if (!_tess.curveTreeV[i]->isLeaf())
- {
- currentVBuf.addBatch(
- patchVerts.begin() + GLint(_tess.curveTreeV[i]->index),
- _tess.m_nArrayWidth
- );
- }
-
- firstIndex += (_tess.arrayHeight[i] * _tess.m_nArrayWidth);
- }
-
- const ArbitraryMeshVertex* p = &patchVerts.front();
- std::size_t uStride = _tess.m_nArrayWidth;
- for (std::size_t i = 0; i <= _tess.curveTreeU.size(); ++i)
- {
- currentVBuf.addBatch(p, _tess.m_nArrayHeight, uStride);
-
- if (i == _tess.curveTreeU.size()) break;
-
- if (!_tess.curveTreeU[i]->isLeaf())
- {
- currentVBuf.addBatch(
- patchVerts.begin() + _tess.curveTreeU[i]->index,
- _tess.m_nArrayHeight, uStride
- );
- }
-
- p += _tess.arrayWidth[i];
- }
-
- // Render all vertex batches
- _vertexBuf.replaceData(currentVBuf);
- }
-
- _vertexBuf.renderAllBatches(GL_LINE_STRIP);
-}
-
-void RenderablePatchWireframe::queueUpdate()
-{
- _needsUpdate = true;
-}
-
-void RenderablePatchFixedWireframe::render(const RenderInfo& info) const
-{
- if (_tess.vertices.empty() || _tess.indices.empty()) return;
-
- // No colour changing
- glDisableClientState(GL_COLOR_ARRAY);
- if (info.checkFlag(RENDER_VERTEX_COLOUR))
- {
- glColor3f(1, 1, 1);
- }
-
- if (_needsUpdate)
- {
- _needsUpdate = false;
-
// Create a VBO and add the vertex data
VertexBuffer_T currentVBuf;
currentVBuf.addVertices(_tess.vertices.begin(), _tess.vertices.end());
@@ -92,10 +22,10 @@ void RenderablePatchFixedWireframe::render(const RenderInfo& info) const
// Submit index batches
const RenderIndex* strip_indices = &_tess.indices.front();
for (std::size_t i = 0;
- i < _tess.m_numStrips;
- i++, strip_indices += _tess.m_lenStrips)
+ i < _tess.numStrips;
+ i++, strip_indices += _tess.lenStrips)
{
- currentVBuf.addIndexBatch(strip_indices, _tess.m_lenStrips);
+ currentVBuf.addIndexBatch(strip_indices, _tess.lenStrips);
}
// Render all index batches
@@ -105,7 +35,7 @@ void RenderablePatchFixedWireframe::render(const RenderInfo& info) const
_vertexBuf.renderAllBatches(GL_QUAD_STRIP);
}
-void RenderablePatchFixedWireframe::queueUpdate()
+void RenderablePatchWireframe::queueUpdate()
{
_needsUpdate = true;
}
@@ -142,10 +72,10 @@ void RenderablePatchSolid::render(const RenderInfo& info) const
// Submit indices
const RenderIndex* strip_indices = &_tess.indices.front();
for (std::size_t i = 0;
- i < _tess.m_numStrips;
- i++, strip_indices += _tess.m_lenStrips)
+ i < _tess.numStrips;
+ i++, strip_indices += _tess.lenStrips)
{
- currentVBuf.addIndexBatch(strip_indices, _tess.m_lenStrips);
+ currentVBuf.addIndexBatch(strip_indices, _tess.lenStrips);
}
// Render all batches
@@ -159,3 +89,73 @@ void RenderablePatchSolid::queueUpdate()
{
_needsUpdate = true;
}
+
+const ShaderPtr& RenderablePatchVectorsNTB::getShader() const
+{
+ return _shader;
+}
+
+RenderablePatchVectorsNTB::RenderablePatchVectorsNTB(const PatchTesselation& tess) :
+ _tess(tess)
+{}
+
+void RenderablePatchVectorsNTB::setRenderSystem(const RenderSystemPtr& renderSystem)
+{
+ if (renderSystem)
+ {
+ _shader = renderSystem->capture("$PIVOT");
+ }
+ else
+ {
+ _shader.reset();
+ }
+}
+
+#define VectorMA( v, s, b, o ) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+
+void RenderablePatchVectorsNTB::render(const RenderInfo& info) const
+{
+ if (_tess.vertices.empty()) return;
+
+ glBegin(GL_LINES);
+
+ for (int j = 0; j < _tess.vertices.size(); j++)
+ {
+ const ArbitraryMeshVertex& v = _tess.vertices[j];
+
+ Vector3 end;
+
+ glColor3f(0, 0, 1);
+ glVertex3dv(static_cast<double*>(Vector3(v.vertex)));
+ VectorMA(v.vertex, 5, v.normal, end);
+ glVertex3dv(static_cast<double*>(end));
+
+ glColor3f(1, 0, 0);
+ glVertex3dv(static_cast<double*>(Vector3(v.vertex)));
+ VectorMA(v.vertex, 5, v.tangent, end);
+ glVertex3dv(static_cast<double*>(end));
+
+ glColor3f(0, 1, 0);
+ glVertex3dv(static_cast<double*>(Vector3(v.vertex)));
+ VectorMA(v.vertex, 5, v.bitangent, end);
+ glVertex3dv(static_cast<double*>(end));
+
+ glColor3f(1, 1, 1);
+ glVertex3dv(static_cast<double*>(Vector3(v.vertex)));
+ glVertex3dv(static_cast<double*>(Vector3(v.vertex)));
+ }
+
+ glEnd();
+}
+
+void RenderablePatchVectorsNTB::render(RenderableCollector& collector, const VolumeTest& volume, const Matrix4& localToWorld) const
+{
+ collector.PushState();
+
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
+ collector.SetState(_shader, RenderableCollector::eWireframeOnly);
+ collector.SetState(_shader, RenderableCollector::eFullMaterials);
+ collector.addRenderable(*this, localToWorld);
+
+ collector.PopState();
+}
diff --git a/radiant/patch/PatchRenderables.h b/radiant/patch/PatchRenderables.h
index ac4bda6..16cb8b8 100644
--- a/radiant/patch/PatchRenderables.h
+++ b/radiant/patch/PatchRenderables.h
@@ -3,7 +3,6 @@
* These are the renderables that are used in the PatchNode/Patch class to draw
* the patch onto the screen.
*/
-
#pragma once
#include "igl.h"
@@ -13,23 +12,26 @@
#include "render/IndexedVertexBuffer.h"
/// Helper class to render a PatchTesselation in wireframe mode
-class RenderablePatchWireframe : public OpenGLRenderable
+class RenderablePatchWireframe :
+ public OpenGLRenderable
{
- // Geometry source
- const PatchTesselation& _tess;
+protected:
+ // Geometry source
+ const PatchTesselation& _tess;
- // VertexBuffer for rendering
- typedef render::VertexBuffer<Vertex3f> VertexBuffer_T;
- mutable VertexBuffer_T _vertexBuf;
+ // VertexBuffer for rendering
+ typedef render::IndexedVertexBuffer<Vertex3f> VertexBuffer_T;
+ mutable VertexBuffer_T _vertexBuf;
- mutable bool _needsUpdate;
+ mutable bool _needsUpdate;
public:
+ RenderablePatchWireframe(const PatchTesselation& tess) :
+ _tess(tess),
+ _needsUpdate(true)
+ { }
- RenderablePatchWireframe(const PatchTesselation& tess) :
- _tess(tess),
- _needsUpdate(true)
- { }
+ virtual ~RenderablePatchWireframe() {}
void render(const RenderInfo& info) const;
@@ -37,27 +39,13 @@ public:
};
/// Helper class to render a fixed geometry PatchTesselation in wireframe mode
-class RenderablePatchFixedWireframe : public OpenGLRenderable
+class RenderablePatchFixedWireframe :
+ public RenderablePatchWireframe
{
- // Geometry source
- PatchTesselation& _tess;
-
- // VertexBuffer for rendering
- typedef render::IndexedVertexBuffer<Vertex3f> VertexBuffer_T;
- mutable VertexBuffer_T _vertexBuf;
-
- mutable bool _needsUpdate;
-
public:
-
RenderablePatchFixedWireframe(PatchTesselation& tess) :
- _tess(tess),
- _needsUpdate(true)
+ RenderablePatchWireframe(tess)
{}
-
- void render(const RenderInfo& info) const;
-
- void queueUpdate();
};
/// Helper class to render a PatchTesselation in solid mode
@@ -80,3 +68,25 @@ public:
void queueUpdate();
};
+
+// Renders a vertex' normal/tangent/bitangent vector (for debugging purposes)
+class RenderablePatchVectorsNTB :
+ public OpenGLRenderable
+{
+private:
+ std::vector<VertexCb> _vertices;
+ const PatchTesselation& _tess;
+
+ ShaderPtr _shader;
+
+public:
+ const ShaderPtr& getShader() const;
+
+ RenderablePatchVectorsNTB(const PatchTesselation& tess);
+
+ void setRenderSystem(const RenderSystemPtr& renderSystem);
+
+ void render(const RenderInfo& info) const;
+
+ void render(RenderableCollector& collector, const VolumeTest& volume, const Matrix4& localToWorld) const;
+};
diff --git a/radiant/patch/PatchTesselation.cpp b/radiant/patch/PatchTesselation.cpp
index 9e50725..8c06998 100644
--- a/radiant/patch/PatchTesselation.cpp
+++ b/radiant/patch/PatchTesselation.cpp
@@ -1,6 +1,877 @@
#include "PatchTesselation.h"
+#include "Patch.h"
+
void PatchTesselation::clear()
{
*this = PatchTesselation();
}
+
+#define COPLANAR_EPSILON 0.1f
+
+void PatchTesselation::generateNormals()
+{
+ //
+ // if all points are coplanar, set all normals to that plane
+ //
+ Vector3 extent[3];
+
+ extent[0] = vertices[width - 1].vertex - vertices[0].vertex;
+ extent[1] = vertices[(height - 1) * width + width - 1].vertex - vertices[0].vertex;
+ extent[2] = vertices[(height - 1) * width].vertex - vertices[0].vertex;
+
+ Vector3 norm = extent[0].crossProduct(extent[1]);
+
+ if (norm.getLengthSquared() == 0.0f)
+ {
+ norm = extent[0].crossProduct(extent[2]);
+
+ if (norm.getLengthSquared() == 0.0f)
+ {
+ norm = extent[1].crossProduct(extent[2]);
+ }
+ }
+
+ // wrapped patched may not get a valid normal here
+ if (norm.normalise() != 0.0f)
+ {
+ float offset = vertices[0].vertex.dot(norm);
+
+ std::size_t i = 0;
+
+ for (i = 1; i < width * height; i++)
+ {
+ float d = vertices[i].vertex.dot(norm);
+
+ if (fabs(d - offset) > COPLANAR_EPSILON)
+ {
+ break;
+ }
+ }
+
+ if (i == width * height)
+ {
+ // all are coplanar
+ for (i = 0; i < width * height; i++)
+ {
+ vertices[i].normal = norm;
+ }
+
+ return;
+ }
+ }
+
+ // check for wrapped edge cases, which should smooth across themselves
+ bool wrapWidth = false;
+
+ {
+ std::size_t i = 0;
+
+ for (i = 0; i < height; i++)
+ {
+ Vector3 delta = vertices[i * width].vertex - vertices[i * width + width - 1].vertex;
+
+ if (delta.getLengthSquared() > 1.0f)
+ {
+ break;
+ }
+ }
+
+ if (i == height)
+ {
+ wrapWidth = true;
+ }
+ }
+
+ bool wrapHeight = false;
+
+ {
+ std::size_t i = 0;
+
+ for (i = 0; i < width; i++)
+ {
+ Vector3 delta = vertices[i].vertex - vertices[(height - 1) * width + i].vertex;
+
+ if (delta.getLengthSquared() > 1.0f)
+ {
+ break;
+ }
+ }
+
+ if (i == width)
+ {
+ wrapHeight = true;
+ }
+ }
+
+ Vector3 around[8];
+ bool good[8];
+ static int neighbors[8][2] = { { 0,1 },{ 1,1 },{ 1,0 },{ 1,-1 },{ 0,-1 },{ -1,-1 },{ -1,0 },{ -1,1 } };
+
+ for (std::size_t i = 0; i < width; i++)
+ {
+ for (std::size_t j = 0; j < height; j++)
+ {
+ Vector3 base = vertices[j * width + i].vertex;
+
+ for (std::size_t k = 0; k < 8; k++)
+ {
+ around[k] = Vector3(0, 0, 0);
+ good[k] = false;
+
+ for (std::size_t dist = 1; dist <= 3; dist++)
+ {
+ int x = i + neighbors[k][0] * dist;
+ int y = j + neighbors[k][1] * dist;
+
+ if (wrapWidth)
+ {
+ if (x < 0)
+ {
+ x = width - 1 + x;
+ }
+ else if (x >= width)
+ {
+ x = 1 + x - width;
+ }
+ }
+
+ if (wrapHeight)
+ {
+ if (y < 0)
+ {
+ y = height - 1 + y;
+ }
+ else if (y >= height)
+ {
+ y = 1 + y - height;
+ }
+ }
+
+ if (x < 0 || x >= width || y < 0 || y >= height)
+ {
+ break; // edge of patch
+ }
+
+ Vector3 temp = vertices[y * width + x].vertex - base;
+
+ if (temp.normalise() == 0.0f)
+ {
+ continue; // degenerate edge, get more dist
+ }
+ else
+ {
+ good[k] = true;
+ around[k] = temp;
+ break; // good edge
+ }
+ }
+ }
+
+ Vector3 sum(0, 0, 0);
+
+ for (std::size_t k = 0; k < 8; k++)
+ {
+ if (!good[k] || !good[(k + 1) & 7])
+ {
+ continue; // didn't get two points
+ }
+
+ Vector3 tempNormal = around[(k + 1) & 7].crossProduct(around[k]);
+ if (tempNormal.normalise() == 0.0f)
+ {
+ continue;
+ }
+
+ sum += tempNormal;
+ }
+
+ vertices[j * width + i].normal = sum;
+ vertices[j * width + i].normal.normalise();
+ }
+ }
+}
+
+void PatchTesselation::sampleSinglePatchPoint(const ArbitraryMeshVertex ctrl[3][3], float u, float v, ArbitraryMeshVertex& out) const
+{
+ float vCtrl[3][8];
+
+ // find the control points for the v coordinate
+ for (std::size_t vPoint = 0; vPoint < 3; vPoint++)
+ {
+ for (std::size_t axis = 0; axis < 8; axis++)
+ {
+ float a, b, c;
+
+ if (axis < 3)
+ {
+ a = ctrl[0][vPoint].vertex[axis];
+ b = ctrl[1][vPoint].vertex[axis];
+ c = ctrl[2][vPoint].vertex[axis];
+ }
+ else if (axis < 6)
+ {
+ a = ctrl[0][vPoint].normal[axis - 3];
+ b = ctrl[1][vPoint].normal[axis - 3];
+ c = ctrl[2][vPoint].normal[axis - 3];
+ }
+ else
+ {
+ a = ctrl[0][vPoint].texcoord[axis - 6];
+ b = ctrl[1][vPoint].texcoord[axis - 6];
+ c = ctrl[2][vPoint].texcoord[axis - 6];
+ }
+
+ float qA = a - 2.0f * b + c;
+ float qB = 2.0f * b - 2.0f * a;
+ float qC = a;
+
+ vCtrl[vPoint][axis] = qA * u * u + qB * u + qC;
+ }
+ }
+
+ // interpolate the v value
+ for (std::size_t axis = 0; axis < 8; axis++)
+ {
+ float a = vCtrl[0][axis];
+ float b = vCtrl[1][axis];
+ float c = vCtrl[2][axis];
+ float qA = a - 2.0f * b + c;
+ float qB = 2.0f * b - 2.0f * a;
+ float qC = a;
+
+ if (axis < 3)
+ {
+ out.vertex[axis] = qA * v * v + qB * v + qC;
+ }
+ else if (axis < 6)
+ {
+ out.normal[axis - 3] = qA * v * v + qB * v + qC;
+ }
+ else
+ {
+ out.texcoord[axis - 6] = qA * v * v + qB * v + qC;
+ }
+ }
+}
+
+void PatchTesselation::sampleSinglePatch(const ArbitraryMeshVertex ctrl[3][3],
+ std::size_t baseCol, std::size_t baseRow,
+ std::size_t w, std::size_t horzSub, std::size_t vertSub,
+ std::vector<ArbitraryMeshVertex>& outVerts) const
+{
+ horzSub++;
+ vertSub++;
+
+ for (std::size_t i = 0; i < horzSub; i++)
+ {
+ for (std::size_t j = 0; j < vertSub; j++)
+ {
+ float u = static_cast<float>(i) / (horzSub - 1);
+ float v = static_cast<float>(j) / (vertSub - 1);
+
+ sampleSinglePatchPoint(ctrl, u, v, outVerts[((baseRow + j) * w) + i + baseCol]);
+ }
+ }
+}
+
+void PatchTesselation::subdivideMeshFixed(std::size_t subdivX, std::size_t subdivY)
+{
+ std::size_t outWidth = ((width - 1) / 2 * subdivX) + 1;
+ std::size_t outHeight = ((height - 1) / 2 * subdivY) + 1;
+
+ std::vector<ArbitraryMeshVertex> dv(outWidth * outHeight);
+
+ std::size_t baseCol = 0;
+ ArbitraryMeshVertex sample[3][3];
+
+ for (std::size_t i = 0; i + 2 < width; i += 2)
+ {
+ std::size_t baseRow = 0;
+
+ for (std::size_t j = 0; j + 2 < height; j += 2)
+ {
+ for (std::size_t k = 0; k < 3; k++)
+ {
+ for (std::size_t l = 0; l < 3; l++)
+ {
+ sample[k][l] = vertices[((j + l) * width) + i + k];
+ }
+ }
+
+ sampleSinglePatch(sample, baseCol, baseRow, outWidth, subdivX, subdivY, dv);
+
+ baseRow += subdivY;
+ }
+
+ baseCol += subdivX;
+ }
+
+ vertices.swap(dv);
+
+ width = _maxWidth = outWidth;
+ height = _maxHeight = outHeight;
+}
+
+void PatchTesselation::collapseMesh()
+{
+ if (width != _maxWidth)
+ {
+ for (std::size_t j = 0; j < height; j++)
+ {
+ for (std::size_t i = 0; i < width; i++)
+ {
+ vertices[j*width + i] = vertices[j*_maxWidth + i];
+ }
+ }
+ }
+
+ vertices.resize(width * height);
+}
+
+void PatchTesselation::expandMesh()
+{
+ vertices.resize(_maxWidth * _maxHeight);
+
+ if (width != _maxWidth)
+ {
+ for (int j = height - 1; j >= 0; j--)
+ {
+ for (int i = width - 1; i >= 0; i--)
+ {
+ vertices[j*_maxWidth + i] = vertices[j*width + i];
+ }
+ }
+ }
+}
+
+void PatchTesselation::resizeExpandedMesh(int newHeight, int newWidth)
+{
+ if (newHeight <= _maxHeight && newWidth <= _maxWidth)
+ {
+ return;
+ }
+
+ if (newHeight * newWidth > _maxHeight * _maxWidth)
+ {
+ vertices.resize(newHeight * newWidth);
+ }
+
+ // space out verts for new height and width
+ for (int j = _maxHeight - 1; j >= 0; j--)
+ {
+ for (int i = _maxWidth - 1; i >= 0; i--)
+ {
+ vertices[j*newWidth + i] = vertices[j*_maxWidth + i];
+ }
+ }
+
+ _maxHeight = newHeight;
+ _maxWidth = newWidth;
+}
+
+void PatchTesselation::lerpVert(const ArbitraryMeshVertex& a, const ArbitraryMeshVertex& b, ArbitraryMeshVertex&out)
+{
+ out.vertex = a.vertex.mid(b.vertex);
+ out.normal = a.normal.mid(b.normal);
+ out.texcoord = a.texcoord.mid(b.texcoord);
+}
+
+void PatchTesselation::putOnCurve()
+{
+ ArbitraryMeshVertex prev, next;
+
+ // put all the approximating points on the curve
+ for (std::size_t i = 0; i < width; i++)
+ {
+ for (std::size_t j = 1; j < height; j += 2)
+ {
+ lerpVert(vertices[j*_maxWidth + i], vertices[(j + 1)*_maxWidth + i], prev);
+ lerpVert(vertices[j*_maxWidth + i], vertices[(j - 1)*_maxWidth + i], next);
+ lerpVert(prev, next, vertices[j*_maxWidth + i]);
+ }
+ }
+
+ for (std::size_t j = 0; j < height; j++)
+ {
+ for (std::size_t i = 1; i < width; i += 2)
+ {
+ lerpVert(vertices[j*_maxWidth + i], vertices[j*_maxWidth + i + 1], prev);
+ lerpVert(vertices[j*_maxWidth + i], vertices[j*_maxWidth + i - 1], next);
+ lerpVert(prev, next, vertices[j*_maxWidth + i]);
+ }
+ }
+}
+
+Vector3 PatchTesselation::projectPointOntoVector(const Vector3& point, const Vector3& vStart, const Vector3& vEnd)
+{
+ Vector3 pVec = point - vStart;
+ Vector3 vec = vEnd - vStart;
+
+ vec.normalise();
+
+ // project onto the directional vector for this segment
+ return vStart + vec * pVec.dot(vec);
+}
+
+void PatchTesselation::removeLinearColumnsRows()
+{
+ for (std::size_t j = 1; j < width - 1; j++)
+ {
+ float maxLength = 0;
+
+ for (std::size_t i = 0; i < height; i++)
+ {
+ Vector3 proj = projectPointOntoVector(vertices[i*_maxWidth + j].vertex,
+ vertices[i*_maxWidth + j - 1].vertex,
+ vertices[i*_maxWidth + j + 1].vertex);
+
+ Vector3 dir = vertices[i*_maxWidth + j].vertex - proj;
+
+ float len = dir.getLengthSquared();
+
+ if (len > maxLength)
+ {
+ maxLength = len;
+ }
+ }
+
+ if (maxLength < 0.2f*0.2f)
+ {
+ width--;
+
+ for (std::size_t i = 0; i < height; i++)
+ {
+ for (std::size_t k = j; k < width; k++)
+ {
+ vertices[i*_maxWidth + k] = vertices[i*_maxWidth + k + 1];
+ }
+ }
+
+ j--;
+ }
+ }
+
+ for (std::size_t j = 1; j < height - 1; j++)
+ {
+ float maxLength = 0;
+
+ for (std::size_t i = 0; i < width; i++)
+ {
+ Vector3 proj = projectPointOntoVector(vertices[j*_maxWidth + i].vertex,
+ vertices[(j - 1)*_maxWidth + i].vertex,
+ vertices[(j + 1)*_maxWidth + i].vertex);
+
+ Vector3 dir = vertices[j*_maxWidth + i].vertex - proj;
+
+ float len = dir.getLengthSquared();
+
+ if (len > maxLength)
+ {
+ maxLength = len;
+ }
+ }
+
+ if (maxLength < 0.2f*0.2f)
+ {
+ height--;
+
+ for (std::size_t i = 0; i < width; i++)
+ {
+ for (std::size_t k = j; k < height; k++)
+ {
+ vertices[k*_maxWidth + i] = vertices[(k + 1)*_maxWidth + i];
+ }
+ }
+
+ j--;
+ }
+ }
+}
+
+void PatchTesselation::subdivideMesh()
+{
+ static const float DEFAULT_CURVE_MAX_ERROR = 4.0f;
+ static const float DEFAULT_CURVE_MAX_LENGTH = -1.0f;
+
+ Vector3 prevxyz, nextxyz, midxyz;
+ ArbitraryMeshVertex prev, next, mid;
+
+ static float maxHorizontalErrorSqr = DEFAULT_CURVE_MAX_ERROR * DEFAULT_CURVE_MAX_ERROR;
+ static float maxVerticalErrorSqr = DEFAULT_CURVE_MAX_ERROR * DEFAULT_CURVE_MAX_ERROR;
+ static float maxLengthSqr = DEFAULT_CURVE_MAX_LENGTH * DEFAULT_CURVE_MAX_LENGTH;
+
+ expandMesh();
+
+ // horizontal subdivisions
+ for (std::size_t j = 0; j + 2 < width; j += 2)
+ {
+ std::size_t i;
+
+ // check subdivided midpoints against control points
+ for (i = 0; i < height; i++)
+ {
+ for (std::size_t l = 0; l < 3; l++)
+ {
+ prevxyz[l] = vertices[i*_maxWidth + j + 1].vertex[l] - vertices[i*_maxWidth + j].vertex[l];
+ nextxyz[l] = vertices[i*_maxWidth + j + 2].vertex[l] - vertices[i*_maxWidth + j + 1].vertex[l];
+ midxyz[l] = (vertices[i*_maxWidth + j].vertex[l] + vertices[i*_maxWidth + j + 1].vertex[l] * 2.0f + vertices[i*_maxWidth + j + 2].vertex[l]) * 0.25f;
+ }
+
+ if (DEFAULT_CURVE_MAX_LENGTH > 0.0f)
+ {
+ // if the span length is too long, force a subdivision
+ if (prevxyz.getLengthSquared() > maxLengthSqr || nextxyz.getLengthSquared() > maxLengthSqr)
+ {
+ break;
+ }
+ }
+
+ // see if this midpoint is off far enough to subdivide
+ Vector3 delta = vertices[i*_maxWidth + j + 1].vertex - midxyz;
+
+ if (delta.getLengthSquared() > maxHorizontalErrorSqr)
+ {
+ break;
+ }
+ }
+
+ if (i == height)
+ {
+ continue; // didn't need subdivision
+ }
+
+ if (width + 2 >= _maxWidth)
+ {
+ resizeExpandedMesh(_maxHeight, _maxWidth + 4);
+ }
+
+ // insert two columns and replace the peak
+ width += 2;
+
+ for (i = 0; i < height; i++)
+ {
+ lerpVert(vertices[i*_maxWidth + j], vertices[i*_maxWidth + j + 1], prev);
+ lerpVert(vertices[i*_maxWidth + j + 1], vertices[i*_maxWidth + j + 2], next);
+ lerpVert(prev, next, mid);
+
+ for (int k = width - 1; k > j + 3; k--)
+ {
+ vertices[i*_maxWidth + k] = vertices[i*_maxWidth + k - 2];
+ }
+ vertices[i*_maxWidth + j + 1] = prev;
+ vertices[i*_maxWidth + j + 2] = mid;
+ vertices[i*_maxWidth + j + 3] = next;
+ }
+
+ // back up and recheck this set again, it may need more subdivision
+ j -= 2;
+ }
+
+ // vertical subdivisions
+ for (std::size_t j = 0; j + 2 < height; j += 2)
+ {
+ int i;
+
+ // check subdivided midpoints against control points
+ for (i = 0; i < width; i++)
+ {
+ for (std::size_t l = 0; l < 3; l++)
+ {
+ prevxyz[l] = vertices[(j + 1)*_maxWidth + i].vertex[l] - vertices[j*_maxWidth + i].vertex[l];
+ nextxyz[l] = vertices[(j + 2)*_maxWidth + i].vertex[l] - vertices[(j + 1)*_maxWidth + i].vertex[l];
+ midxyz[l] = (vertices[j*_maxWidth + i].vertex[l] + vertices[(j + 1)*_maxWidth + i].vertex[l] * 2.0f + vertices[(j + 2)*_maxWidth + i].vertex[l]) * 0.25f;
+ }
+
+ if (DEFAULT_CURVE_MAX_LENGTH > 0.0f)
+ {
+ // if the span length is too long, force a subdivision
+ if (prevxyz.getLengthSquared() > maxLengthSqr || nextxyz.getLengthSquared() > maxLengthSqr)
+ {
+ break;
+ }
+ }
+
+ // see if this midpoint is off far enough to subdivide
+ Vector3 delta = vertices[(j + 1)*_maxWidth + i].vertex - midxyz;
+
+ if (delta.getLengthSquared() > maxVerticalErrorSqr)
+ {
+ break;
+ }
+ }
+
+ if (i == width)
+ {
+ continue; // didn't need subdivision
+ }
+
+ if (height + 2 >= _maxHeight)
+ {
+ resizeExpandedMesh(_maxHeight + 4, _maxWidth);
+ }
+
+ // insert two columns and replace the peak
+ height += 2;
+
+ for (i = 0; i < width; i++)
+ {
+ lerpVert(vertices[j*_maxWidth + i], vertices[(j + 1)*_maxWidth + i], prev);
+ lerpVert(vertices[(j + 1)*_maxWidth + i], vertices[(j + 2)*_maxWidth + i], next);
+ lerpVert(prev, next, mid);
+
+ for (int k = height - 1; k > j + 3; k--)
+ {
+ vertices[k*_maxWidth + i] = vertices[(k - 2)*_maxWidth + i];
+ }
+
+ vertices[(j + 1)*_maxWidth + i] = prev;
+ vertices[(j + 2)*_maxWidth + i] = mid;
+ vertices[(j + 3)*_maxWidth + i] = next;
+ }
+
+ // back up and recheck this set again, it may need more subdivision
+ j -= 2;
+ }
+
+ putOnCurve();
+
+ removeLinearColumnsRows();
+
+ collapseMesh();
+}
+
+struct FaceTangents
+{
+ Vector3 tangents[2];
+};
+
+namespace
+{
+
+void calculateFaceTangent(FaceTangents& ft, const ArbitraryMeshVertex& a, const ArbitraryMeshVertex& b, const ArbitraryMeshVertex& c)
+{
+ float d0[5], d1[5];
+
+ d0[0] = b.vertex[0] - a.vertex[0];
+ d0[1] = b.vertex[1] - a.vertex[1];
+ d0[2] = b.vertex[2] - a.vertex[2];
+ d0[3] = b.texcoord[0] - a.texcoord[0];
+ d0[4] = b.texcoord[1] - a.texcoord[1];
+
+ d1[0] = c.vertex[0] - a.vertex[0];
+ d1[1] = c.vertex[1] - a.vertex[1];
+ d1[2] = c.vertex[2] - a.vertex[2];
+ d1[3] = c.texcoord[0] - a.texcoord[0];
+ d1[4] = c.texcoord[1] - a.texcoord[1];
+
+ float area = d0[3] * d1[4] - d0[4] * d1[3];
+
+ if (fabs(area) < 1e-20f)
+ {
+ ft.tangents[0].set(0, 0, 0);
+ ft.tangents[1].set(0, 0, 0);
+ return;
+ }
+
+ float inva = area < 0.0f ? -1 : 1; // was = 1.0f / area;
+
+ Vector3 temp;
+
+ temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
+ temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
+ temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
+ temp.normalise();
+ ft.tangents[0] = temp.getNormalised();
+
+ temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
+ temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
+ temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
+ temp.normalise();
+ ft.tangents[1] = temp;
+}
+
+} // namespace
+
+void PatchTesselation::deriveFaceTangents(std::vector<FaceTangents>& faceTangents)
+{
+ assert(lenStrips >= 3);
+
+ // calculate tangent vectors for each face in isolation
+
+ // DR is using indices that are sent to openGL as GL_QUAD_STRIPs
+ // It takes N+2 indices to describe N triangles when using QUAD_STRIPs
+ std::size_t numFacesPerStrip = lenStrips - 2;
+ std::size_t numFaces = numFacesPerStrip * numStrips;
+
+ faceTangents.resize(numFaces); // one tangent per face
+
+ // Go through each strip and derive tangents for each triangle like idTech4 does
+ const RenderIndex* strip_indices = &indices.front();
+
+ for (std::size_t strip = 0; strip < numStrips; strip++, strip_indices += lenStrips)
+ {
+ for (std::size_t i = 0; i < lenStrips - 2; i += 2)
+ {
+ // First tri of the quad (indices 0,1,2)
+ calculateFaceTangent(faceTangents[strip*numFacesPerStrip + i],
+ vertices[strip_indices[i + 0]],
+ vertices[strip_indices[i + 1]],
+ vertices[strip_indices[i + 2]]);
+
+ // Second tri of the quad (indices 1,2,3)
+ calculateFaceTangent(faceTangents[strip*numFacesPerStrip + i + 1],
+ vertices[strip_indices[i + 1]],
+ vertices[strip_indices[i + 2]],
+ vertices[strip_indices[i + 3]]);
+ }
+ }
+}
+
+void PatchTesselation::deriveTangents()
+{
+ if (lenStrips < 2) return;
+
+ std::vector<FaceTangents> faceTangents;
+ deriveFaceTangents(faceTangents);
+
+ // Note: we don't clear the tangent vectors here since the calling code
+ // just allocated the mesh which initialises all vectors to 0,0,0
+
+ std::size_t numFacesPerStrip = lenStrips - 2;
+
+ // The sum of all tangent vectors is assigned to each vertex of every face
+ // Since vertices can be shared across triangles this might very well add
+ // tangents of neighbouring triangles too
+ const RenderIndex* strip_indices = &indices.front();
+
+ for (std::size_t strip = 0; strip < numStrips; strip++, strip_indices += lenStrips)
+ {
+ for (std::size_t i = 0; i < lenStrips - 2; i += 2)
+ {
+ // First tri of the quad
+ const FaceTangents& ft1 = faceTangents[strip*numFacesPerStrip + i];
+
+ for (std::size_t j = 0; j < 3; j++)
+ {
+ ArbitraryMeshVertex& vert = vertices[strip_indices[i + j]];
+
+ vert.tangent += ft1.tangents[0];
+ vert.bitangent += ft1.tangents[1];
+ }
+
+ // Second tri of the quad
+ const FaceTangents& ft2 = faceTangents[strip*numFacesPerStrip + i + 1];
+
+ for (std::size_t j = 0; j < 3; j++)
+ {
+ ArbitraryMeshVertex& vert = vertices[strip_indices[i + j + 1]];
+
+ vert.tangent += ft2.tangents[0];
+ vert.bitangent += ft2.tangents[1];
+ }
+ }
+ }
+
+ // project the summed vectors onto the normal plane
+ // and normalize. The tangent vectors will not necessarily
+ // be orthogonal to each other, but they will be orthogonal
+ // to the surface normal.
+ for (ArbitraryMeshVertex& vert : vertices)
+ {
+ float d = vert.tangent.dot(vert.normal);
+ vert.tangent = vert.tangent - vert.normal * d;
+ vert.tangent.normalise();
+
+ d = vert.bitangent.dot(vert.normal);
+ vert.bitangent = vert.bitangent - vert.normal * d;
+ vert.bitangent.normalise();
+ }
+}
+
+void PatchTesselation::generateIndices()
+{
+ const std::size_t numElems = width*height; // total number of elements in vertex array
+
+ const bool bWidthStrips = (width >= height); // decide if horizontal strips are longer than vertical
+
+ // allocate vertex, normal, texcoord and primitive-index arrays
+ vertices.resize(numElems);
+ indices.resize(width * 2 * (height - 1));
+
+ // set up strip indices
+ if (bWidthStrips)
+ {
+ numStrips = height - 1;
+ lenStrips = width * 2;
+
+ for (std::size_t i = 0; i<width; i++)
+ {
+ for (std::size_t j = 0; j<numStrips; j++)
+ {
+ indices[(j*lenStrips) + i * 2] = RenderIndex(j*width + i);
+ indices[(j*lenStrips) + i * 2 + 1] = RenderIndex((j + 1)*width + i);
+ }
+ }
+ }
+ else
+ {
+ numStrips = width - 1;
+ lenStrips = height * 2;
+
+ for (std::size_t i = 0; i<height; i++)
+ {
+ for (std::size_t j = 0; j<numStrips; j++)
+ {
+ indices[(j*lenStrips) + i * 2] = RenderIndex(((height - 1) - i)*width + j);
+ indices[(j*lenStrips) + i * 2 + 1] = RenderIndex(((height - 1) - i)*width + j + 1);
+ }
+ }
+ }
+}
+
+void PatchTesselation::generate(std::size_t patchWidth, std::size_t patchHeight,
+ const PatchControlArray& controlPoints, bool subdivionsFixed, const Subdivisions& subdivs)
+{
+ width = patchWidth;
+ height = patchHeight;
+
+ _maxWidth = width;
+ _maxHeight = height;
+
+ // We start off with the control vertex grid, copy it into our tesselation structure
+ vertices.resize(controlPoints.size());
+
+ for (std::size_t w = 0; w < width; w++)
+ {
+ for (std::size_t h = 0; h < height; h++)
+ {
+ vertices[h*width + w].vertex = controlPoints[h*width + w].vertex;
+ vertices[h*width + w].texcoord = controlPoints[h*width + w].texcoord;
+ }
+ }
+
+ // generate normals for the control mesh
+ generateNormals();
+
+ if (subdivionsFixed)
+ {
+ subdivideMeshFixed(subdivs.x(), subdivs.y());
+ }
+ else
+ {
+ subdivideMesh();
+ }
+
+ // normalize all the lerped normals
+ for (ArbitraryMeshVertex& vertex : vertices)
+ {
+ vertex.normal.normalise();
+ }
+
+ // Build the strip indices for rendering the quads
+ generateIndices();
+
+ // With indices in place we can derive the tangent/bitangent vectors
+ deriveTangents();
+}
diff --git a/radiant/patch/PatchTesselation.h b/radiant/patch/PatchTesselation.h
index 5b6925e..3385639 100644
--- a/radiant/patch/PatchTesselation.h
+++ b/radiant/patch/PatchTesselation.h
@@ -1,37 +1,72 @@
#pragma once
#include "render.h"
-#include "PatchBezier.h"
+#include "PatchControl.h"
+
+struct FaceTangents;
/// Representation of a patch as mesh geometry
-struct PatchTesselation
+class PatchTesselation
{
public:
-
+ // The vertex data, each vertex equipped with texcoord and ntb vectors
std::vector<ArbitraryMeshVertex> vertices;
+
+ // The indices, arranged in the way it's expected by GL_QUAD_STRIPS
+ // The number of indices is (lenStrips*numStrips), which is the same as (width*height)
std::vector<RenderIndex> indices;
- std::size_t m_numStrips;
- std::size_t m_lenStrips;
+ // Strip index layout
+ std::size_t numStrips;
+ std::size_t lenStrips;
- std::vector<std::size_t> arrayWidth;
- std::size_t m_nArrayWidth;
- std::vector<std::size_t> arrayHeight;
- std::size_t m_nArrayHeight;
+ // Geometry of the tesselated mesh
+ std::size_t width;
+ std::size_t height;
- std::vector<BezierCurveTree*> curveTreeU;
- std::vector<BezierCurveTree*> curveTreeV;
+private:
+ // Used during the tesselation phase
+ std::size_t _maxWidth;
+ std::size_t _maxHeight;
public:
/// Construct an uninitialised patch tesselation
PatchTesselation() :
- m_numStrips(0),
- m_lenStrips(0),
- m_nArrayWidth(0),
- m_nArrayHeight(0)
+ numStrips(0),
+ lenStrips(0),
+ width(0),
+ height(0),
+ _maxWidth(0),
+ _maxHeight(0)
{}
/// Clear all patch data
void clear();
+
+ // Generates the tesselated mesh based on the input parameters
+ void generate(std::size_t width, std::size_t height, const PatchControlArray& controlPoints,
+ bool subdivionsFixed, const Subdivisions& subdivs);
+
+private:
+ // Private methods used for tesselation, modeled after the patch subdivision code found in idTech4
+ void generateIndices();
+ void generateNormals();
+ void subdivideMesh();
+ void subdivideMeshFixed(std::size_t subdivX, std::size_t subdivY);
+ void collapseMesh();
+ void expandMesh();
+ void resizeExpandedMesh(int newHeight, int newWidth);
+ void putOnCurve();
+ void removeLinearColumnsRows();
+
+ static void lerpVert(const ArbitraryMeshVertex& a, const ArbitraryMeshVertex& b, ArbitraryMeshVertex&out);
+ static Vector3 projectPointOntoVector(const Vector3& point, const Vector3& vStart, const Vector3& vEnd);
+
+ void sampleSinglePatch(const ArbitraryMeshVertex ctrl[3][3], std::size_t baseCol, std::size_t baseRow,
+ std::size_t width, std::size_t horzSub, std::size_t vertSub,
+ std::vector<ArbitraryMeshVertex>& outVerts) const;
+ void sampleSinglePatchPoint(const ArbitraryMeshVertex ctrl[3][3], float u, float v, ArbitraryMeshVertex& out) const;
+ void deriveTangents();
+ void deriveFaceTangents(std::vector<FaceTangents>& faceTangents);
};
diff --git a/radiant/referencecache/NullModelNode.h b/radiant/referencecache/NullModelNode.h
index 2c6c51f..b720bfd 100644
--- a/radiant/referencecache/NullModelNode.h
+++ b/radiant/referencecache/NullModelNode.h
@@ -35,13 +35,13 @@ public:
void testSelect(Selector& selector, SelectionTest& test);
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
- void setRenderSystem(const RenderSystemPtr& renderSystem);
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override;
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
// Bounded implementation
diff --git a/radiant/render/backend/GLProgramFactory.cpp b/radiant/render/backend/GLProgramFactory.cpp
index e01ac3a..2b88b86 100644
--- a/radiant/render/backend/GLProgramFactory.cpp
+++ b/radiant/render/backend/GLProgramFactory.cpp
@@ -100,7 +100,7 @@ GLProgramFactory::getFileAsBuffer(const std::string& filename,
std::string absFileName = getBuiltInGLProgramPath(filename);
// Open the file
- std::size_t size = file_size(absFileName.c_str());
+ std::size_t size = os::getFileSize(absFileName);
std::ifstream file(absFileName.c_str());
// Throw an exception if the file could not be found
diff --git a/radiant/render/backend/OpenGLShader.cpp b/radiant/render/backend/OpenGLShader.cpp
index e7d5738..1cfb04b 100644
--- a/radiant/render/backend/OpenGLShader.cpp
+++ b/radiant/render/backend/OpenGLShader.cpp
@@ -783,6 +783,18 @@ void OpenGLShader::construct(const std::string& name)
state.m_linewidth = 2;
state.m_linestipple_factor = 3;
}
+ else if (name == "$XY_OVERLAY_GROUP")
+ {
+ Vector3 colorSelBrushes(0, 0.4, 0.8);
+ state.setColour(colorSelBrushes[0],
+ colorSelBrushes[1],
+ colorSelBrushes[2],
+ 1);
+ state.setRenderFlag(RENDER_LINESTIPPLE);
+ state.setSortPosition(OpenGLState::SORT_OVERLAY_FIRST);
+ state.m_linewidth = 2;
+ state.m_linestipple_factor = 3;
+ }
else if (name == "$DEBUG_CLIPPED")
{
state.setRenderFlag(RENDER_DEPTHWRITE);
@@ -848,6 +860,24 @@ void OpenGLShader::construct(const std::string& name)
| RENDER_POLYGONSTIPPLE);
state.setSortPosition(OpenGLState::SORT_OVERLAY_FIRST);
}
+ else if (name == "$AAS_AREA")
+ {
+ state.setColour(1, 1, 1, 1);
+ state.setRenderFlags(RENDER_DEPTHWRITE
+ | RENDER_DEPTHTEST
+ | RENDER_OVERRIDE);
+ state.setSortPosition(OpenGLState::SORT_OVERLAY_LAST);
+ state.setDepthFunc(GL_LEQUAL);
+
+ OpenGLState& hiddenLine = appendDefaultPass();
+ hiddenLine.setColour(1, 1, 1, 1);
+ hiddenLine.setRenderFlags(RENDER_DEPTHWRITE
+ | RENDER_DEPTHTEST
+ | RENDER_OVERRIDE
+ | RENDER_LINESTIPPLE);
+ hiddenLine.setSortPosition(OpenGLState::SORT_OVERLAY_LAST);
+ hiddenLine.setDepthFunc(GL_GREATER);
+ }
else
{
assert(false);
diff --git a/radiant/render/frontend/RenderableCollectionWalker.h b/radiant/render/frontend/RenderableCollectionWalker.h
index 6db6daa..adca455 100644
--- a/radiant/render/frontend/RenderableCollectionWalker.h
+++ b/radiant/render/frontend/RenderableCollectionWalker.h
@@ -77,18 +77,31 @@ public:
node->viewChanged();
- if (node->isHighlighted() || (parent != NULL && parent->isHighlighted()))
+ std::size_t highlightFlags = node->getHighlightFlags();
+
+ if (parent)
+ {
+ highlightFlags |= parent->getHighlightFlags();
+ }
+
+ if (highlightFlags & Renderable::Highlight::Selected)
{
if (GlobalSelectionSystem().Mode() != SelectionSystem::eComponent)
{
- _collector.highlightFaces(true);
+ _collector.setHighlightFlag(RenderableCollector::Highlight::Faces, true);
}
else
{
node->renderComponents(_collector, _volume);
}
- _collector.highlightPrimitives(true);
+ _collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, true);
+
+ // Pass on the info about whether we have a group member selected
+ if (highlightFlags & Renderable::Highlight::GroupMember)
+ {
+ _collector.setHighlightFlag(RenderableCollector::Highlight::GroupMember, true);
+ }
}
render(*node);
diff --git a/radiant/selection/BasicSelectable.h b/radiant/selection/BasicSelectable.h
index abbec98..32b8314 100644
--- a/radiant/selection/BasicSelectable.h
+++ b/radiant/selection/BasicSelectable.h
@@ -11,7 +11,7 @@ namespace selection
* the selected state by means of a boolean.
*/
class BasicSelectable :
- public Selectable
+ public ISelectable
{
private:
bool _selected;
diff --git a/radiant/selection/Device.h b/radiant/selection/Device.h
index ebd578b..fccaaf1 100644
--- a/radiant/selection/Device.h
+++ b/radiant/selection/Device.h
@@ -1,39 +1,27 @@
-#ifndef DEVICE_H_
-#define DEVICE_H_
+#pragma once
#include "math/Vector2.h"
-#include <functional>
+#include <algorithm>
-// A vector representing the mouse pointer coordinates
-typedef Vector2 DeviceVector;
-typedef Vector2 WindowVector;
-typedef struct _GdkEventButton GdkEventButton;
-
-inline float screen_normalised(float pos, std::size_t size) {
- return ((2.0f * pos) / size) - 1.0f;
+// Maps the range [0..size] to [-1..+1]
+inline float screen_normalised(Vector2::ElementType pos, std::size_t size)
+{
+ return ((2.0f * pos) / size) - 1.0f;
}
-inline DeviceVector window_to_normalised_device(Vector2 window, std::size_t width, std::size_t height) {
- return DeviceVector(screen_normalised(window.x(), width), screen_normalised(height - 1 - window.y(), height));
+inline Vector2 window_to_normalised_device(const Vector2& window, std::size_t width, std::size_t height)
+{
+ return Vector2(screen_normalised(window.x(), width), screen_normalised(height - 1 - window.y(), height));
}
-/* greebo: This returns a number between -1 and +1
- * returns -1, if pos < -1
- * returns pos, if -1 < pos < +1
- * returns +1, if pos > +1
- *
- * So this performs some kind of cut-off of the value <pos> at the [-1,+1] boundaries
- */
-inline float device_constrained(float pos) {
- return std::min(1.0f, std::max(-1.0f, pos));
+// Constrains the value pos to the range [-1..+1]
+inline Vector2::ElementType device_constrained(Vector2::ElementType pos)
+{
+ return std::min(1.0, std::max(-1.0, pos));
}
-// See device_constrained(float), this cuts off the DeviceVector's components at -1 or +1
-inline DeviceVector device_constrained(DeviceVector device) {
- return DeviceVector(device_constrained(device.x()), device_constrained(device.y()));
+// See device_constrained(), this cuts off the Vector's components at -1 or +1
+inline Vector2 device_constrained(const Vector2& device)
+{
+ return Vector2(device_constrained(device.x()), device_constrained(device.y()));
}
-
-// greebo: The mouseOperations callbacks, should they really be a global?
-typedef std::function<void (const DeviceVector&)> MouseEventCallback;
-
-#endif /*DEVICE_H_*/
diff --git a/radiant/selection/DragManipulator.cpp b/radiant/selection/DragManipulator.cpp
index 6171171..235dc7c 100644
--- a/radiant/selection/DragManipulator.cpp
+++ b/radiant/selection/DragManipulator.cpp
@@ -111,7 +111,7 @@ void DragManipulator::testSelect(const render::View& view, const Matrix4& pivot2
ComponentSelector selectionTester(bestSelector, test, GlobalSelectionSystem().ComponentMode());
GlobalSelectionSystem().foreachSelected(selectionTester);
- for (std::list<Selectable*>::iterator i = bestSelector.best().begin();
+ for (std::list<ISelectable*>::iterator i = bestSelector.best().begin();
i != bestSelector.best().end(); ++i)
{
// greebo: Disabled this, it caused the currently selected patch vertices being deselected.
diff --git a/radiant/selection/OccludeSelector.h b/radiant/selection/OccludeSelector.h
index b52e2ad..0ceb2cc 100644
--- a/radiant/selection/OccludeSelector.h
+++ b/radiant/selection/OccludeSelector.h
@@ -20,7 +20,7 @@ public:
_occluded = false;
}
- void pushSelectable(Selectable& selectable) {}
+ void pushSelectable(ISelectable& selectable) {}
void popSelectable() {}
void addIntersection(const SelectionIntersection& intersection)
diff --git a/radiant/selection/RadiantSelectionSystem.cpp b/radiant/selection/RadiantSelectionSystem.cpp
index 4a4a518..35b755e 100644
--- a/radiant/selection/RadiantSelectionSystem.cpp
+++ b/radiant/selection/RadiantSelectionSystem.cpp
@@ -2,8 +2,10 @@
#include "iundo.h"
#include "igrid.h"
+#include "iselectiongroup.h"
#include "iradiant.h"
#include "ieventmanager.h"
+#include "ilightnode.h"
#include "imousetoolmanager.h"
#include "editable.h"
#include "Selectors.h"
@@ -23,39 +25,9 @@
// Initialise the shader pointer
ShaderPtr RadiantSelectionSystem::_state;
- namespace {
- const std::string RKEY_ROTATION_PIVOT = "user/ui/rotationPivotIsOrigin";
- }
-
-// ------------ Helper Functions --------------------------------------------
-
-inline void matrix4_assign_rotation(Matrix4& matrix, const Matrix4& other) {
- matrix[0] = other[0];
- matrix[1] = other[1];
- matrix[2] = other[2];
- matrix[4] = other[4];
- matrix[5] = other[5];
- matrix[6] = other[6];
- matrix[8] = other[8];
- matrix[9] = other[9];
- matrix[10] = other[10];
-}
-
-void matrix4_assign_rotation_for_pivot(Matrix4& matrix, const scene::INodePtr& node)
+namespace
{
-#if 0
- EditablePtr editable = Node_getEditable(node);
- // If the instance is editable, take the localpivot point into account, otherwise just apply the rotation
- if (editable != 0) {
- matrix4_assign_rotation(matrix, node->localToWorld().getMultipliedBy(editable->getLocalPivot()));
- }
- else
- {
- matrix4_assign_rotation(matrix, node->localToWorld());
- }
-#else
- return;
-#endif
+ const std::string RKEY_ROTATION_PIVOT = "user/ui/rotationPivotIsOrigin";
}
// --------- RadiantSelectionSystem Implementation ------------------------------------------
@@ -221,7 +193,7 @@ void RadiantSelectionSystem::pivotChanged() const
SceneChangeNotify();
}
-void RadiantSelectionSystem::pivotChangedSelection(const Selectable& selectable) {
+void RadiantSelectionSystem::pivotChangedSelection(const ISelectable& selectable) {
pivotChanged();
}
@@ -278,8 +250,8 @@ std::size_t RadiantSelectionSystem::countSelectedComponents() const {
}
// This is called if the selection changes, so that the local list of selected nodes can be updated
-void RadiantSelectionSystem::onSelectedChanged(const scene::INodePtr& node, const Selectable& selectable) {
-
+void RadiantSelectionSystem::onSelectedChanged(const scene::INodePtr& node, const ISelectable& selectable)
+{
// Cache the selection state
bool isSelected = selectable.isSelected();
int delta = isSelected ? +1 : -1;
@@ -324,8 +296,8 @@ void RadiantSelectionSystem::onSelectedChanged(const scene::INodePtr& node, cons
// greebo: This should be called "onComponentSelectionChanged", as it is a similar function of the above one
// Updates the internal list of component nodes if the component selection gets changed
-void RadiantSelectionSystem::onComponentSelection(const scene::INodePtr& node, const Selectable& selectable) {
-
+void RadiantSelectionSystem::onComponentSelection(const scene::INodePtr& node, const ISelectable& selectable)
+{
int delta = selectable.isSelected() ? +1 : -1;
_countComponent += delta;
@@ -600,59 +572,101 @@ void RadiantSelectionSystem::SelectPoint(const render::View& view,
}
// Was the selection test successful (have we found anything to select)?
- if (candidates.size() > 0) {
- // Yes, now determine how we should interpret the click
- switch (modifier) {
- // If we are in toggle mode (Shift-Left-Click by default), just toggle the
- // selection of the "topmost" item
- case SelectionSystem::eToggle: {
- Selectable* best = *candidates.begin();
- // toggle selection of the object with least depth (=first in the list)
- best->setSelected(!best->isSelected());
- }
- break;
- // greebo: eReplace mode gets active as soon as the user holds the replace modifiers down
- // and clicks (by default: Alt-Shift). eReplace is only active during the first click
- // afterwards we are in cycle mode.
- // if cycle mode not enabled, enable it
- case SelectionSystem::eReplace: {
- // select closest (=first in the list)
- (*candidates.begin())->setSelected(true);
- }
- break;
- // select the next object in the list from the one already selected
- // greebo: eCycle is set if the user keeps holding the replace modifiers (Alt-Shift)
- // and does NOT move the mouse between the clicks, otherwise we fall back into eReplace mode
- // Note: The mode is set in SelectObserver::testSelect()
- case SelectionSystem::eCycle: {
- // Cycle through the selection pool and activate the item right after the currently selected
- SelectablesList::iterator i = candidates.begin();
-
- while (i != candidates.end()) {
- if ((*i)->isSelected()) {
- // unselect the currently selected one
- (*i)->setSelected(false);
- // check if there is a "next" item in the list, if not: select the first item
- ++i;
- if (i != candidates.end()) {
- (*i)->setSelected(true);
- }
- else {
- (*candidates.begin())->setSelected(true);
- }
- break;
- }
- ++i;
- } // while
- } // case
- break;
- default:
- break;
- } // switch
- }
+ performPointSelection(candidates, modifier);
}
}
+namespace algorithm
+{
+
+// If the selectable is a GroupSelectable, the respective callback is used
+inline void setSelectionStatus(ISelectable* selectable, bool selected)
+{
+ IGroupSelectable* groupSelectable = dynamic_cast<IGroupSelectable*>(selectable);
+
+ if (groupSelectable)
+ {
+ groupSelectable->setSelected(selected, true); // propagate selection state to group peers
+ }
+ else
+ {
+ selectable->setSelected(selected);
+ }
+}
+
+}
+
+void RadiantSelectionSystem::performPointSelection(const SelectablesList& candidates, EModifier modifier)
+{
+ if (candidates.empty()) return;
+
+ // Yes, now determine how we should interpret the click
+ switch (modifier)
+ {
+ // If we are in toggle mode (Shift-Left-Click by default), just toggle the
+ // selection of the "topmost" item
+ case eToggle:
+ {
+ ISelectable* best = candidates.front();
+ // toggle selection of the object with least depth (=first in the list)
+ algorithm::setSelectionStatus(best, !best->isSelected());
+ }
+ break;
+
+ // greebo: eReplace mode gets active as soon as the user holds the replace modifiers down
+ // and clicks (by default: Alt-Shift). eReplace is only active during the first click
+ // afterwards we are in cycle mode.
+ // if cycle mode not enabled, enable it
+ case eReplace:
+ {
+ // select closest (=first in the list)
+ algorithm::setSelectionStatus(candidates.front(), true);
+ }
+ break;
+
+ // select the next object in the list from the one already selected
+ // greebo: eCycle is set if the user keeps holding the replace modifiers (Alt-Shift)
+ // and does NOT move the mouse between the clicks, otherwise we fall back into eReplace mode
+ // Note: The mode is set in SelectObserver::testSelect()
+ case eCycle:
+ {
+ // Cycle through the selection pool and activate the item right after the currently selected
+ SelectablesList::const_iterator i = candidates.begin();
+
+ while (i != candidates.end())
+ {
+ if ((*i)->isSelected())
+ {
+ // unselect the currently selected one
+ algorithm::setSelectionStatus(*i, false);
+ //(*i)->setSelected(false);
+
+ // check if there is a "next" item in the list, if not: select the first item
+ ++i;
+
+ if (i != candidates.end())
+ {
+ algorithm::setSelectionStatus(*i, true);
+ //(*i)->setSelected(true);
+ }
+ else
+ {
+ algorithm::setSelectionStatus(candidates.front(), true);
+ //candidates.front()->setSelected(true);
+ }
+ break;
+ }
+
+ ++i;
+ }
+ }
+ break;
+
+ default:
+ break;
+ };
+}
+
/* greebo: This gets called by the SelectObserver if the user drags a box and holds down
* any of the selection modifiers. Possible selection candidates are determined and selected/deselected
*/
@@ -697,10 +711,21 @@ void RadiantSelectionSystem::SelectArea(const render::View& view,
testSelectScene(candidates, volume, scissored, Mode(), ComponentMode());
}
- // Cycle through the selection pool and toggle the candidates, but only if we are in toggle mode
- for (SelectablesList::iterator i = candidates.begin(); i != candidates.end(); i++) {
- (*i)->setSelected(!(modifier == SelectionSystem::eToggle && (*i)->isSelected()));
- }
+ // Since toggling a selectable might trigger a group-selection
+ // we need to keep track of the desired state of each selectable
+ typedef std::map<ISelectable*, bool> SelectablesMap;
+ SelectablesMap selectableStates;
+
+ for (ISelectable* selectable : candidates)
+ {
+ bool desiredState = !(modifier == SelectionSystem::eToggle && selectable->isSelected());
+ selectableStates.insert(SelectablesMap::value_type(selectable, desiredState));
+ }
+
+ for (const SelectablesMap::value_type& state : selectableStates)
+ {
+ algorithm::setSelectionStatus(state.first, state.second);
+ }
}
}
@@ -741,8 +766,6 @@ void RadiantSelectionSystem::rotate(const Quaternion& rotation)
if (Mode() == eComponent)
{
Scene_Rotate_Component_Selected(GlobalSceneGraph(), _rotation, _pivot2world.t().getVector3());
-
- matrix4_assign_rotation_for_pivot(_pivot2world, _componentSelection.ultimate());
}
else
{
@@ -1006,8 +1029,6 @@ void RadiantSelectionSystem::keyChanged()
/* greebo: This calculates and constructs the pivot point of the selection.
* It cycles through all selected objects and creates its AABB. The origin point of the AABB
* is basically the pivot point. Pivot2World is therefore a translation from (0,0,0) to the calculated origin.
- *
- * The pivot point is also snapped to the grid.
*/
void RadiantSelectionSystem::ConstructPivot()
{
@@ -1020,7 +1041,13 @@ void RadiantSelectionSystem::ConstructPivot()
if (!nothingSelected())
{
- if (_selectionInfo.entityCount == 1 && _selectionInfo.totalCount == 1 &&
+ if (_selectionInfo.entityCount == 1 && _selectionInfo.totalCount == 1 &&
+ Node_getLightNode(ultimateSelected()))
+ {
+ // When a single light is selected, use the origin for rotation
+ objectPivot = Node_getLightNode(ultimateSelected())->getSelectAABB().origin;
+ }
+ else if (_selectionInfo.entityCount == 1 && _selectionInfo.totalCount == 1 &&
registry::getValue<bool>(RKEY_ROTATION_PIVOT))
{
// Test, if a single entity is selected
@@ -1057,30 +1084,6 @@ void RadiantSelectionSystem::ConstructPivot()
// The pivot2world matrix is just a translation from the world origin (0,0,0) to the object pivot
_pivot2world = Matrix4::getTranslation(objectPivot);
-
- // Only rotation and scaling need further calculations
- switch (_manipulatorMode) {
- case eTranslate:
- break;
- case eRotate:
- if (Mode() == eComponent) {
- matrix4_assign_rotation_for_pivot(_pivot2world, _componentSelection.ultimate());
- }
- else {
- matrix4_assign_rotation_for_pivot(_pivot2world, _selection.ultimate());
- }
- break;
- case eScale:
- if (Mode() == eComponent) {
- matrix4_assign_rotation_for_pivot(_pivot2world, _componentSelection.ultimate());
- }
- else {
- matrix4_assign_rotation_for_pivot(_pivot2world, _selection.ultimate());
- }
- break;
- default:
- break;
- } // switch
}
}
/* greebo: Renders the currently active manipulator by setting the render state and
@@ -1088,8 +1091,8 @@ void RadiantSelectionSystem::ConstructPivot()
*/
void RadiantSelectionSystem::renderSolid(RenderableCollector& collector, const VolumeTest& volume) const {
if (!nothingSelected()) {
- collector.highlightFaces(false);
- collector.highlightPrimitives(false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Faces, false);
+ collector.setHighlightFlag(RenderableCollector::Highlight::Primitives, false);
collector.SetState(_state, RenderableCollector::eWireframeOnly);
collector.SetState(_state, RenderableCollector::eFullMaterials);
@@ -1113,16 +1116,20 @@ const std::string& RadiantSelectionSystem::getName() const {
return _name;
}
-const StringSet& RadiantSelectionSystem::getDependencies() const {
+const StringSet& RadiantSelectionSystem::getDependencies() const
+{
static StringSet _dependencies;
- if (_dependencies.empty()) {
+ if (_dependencies.empty())
+ {
_dependencies.insert(MODULE_RENDERSYSTEM);
_dependencies.insert(MODULE_EVENTMANAGER);
_dependencies.insert(MODULE_XMLREGISTRY);
+ _dependencies.insert(MODULE_RADIANT);
_dependencies.insert(MODULE_GRID);
_dependencies.insert(MODULE_SCENEGRAPH);
_dependencies.insert(MODULE_MOUSETOOLMANAGER);
+ _dependencies.insert(MODULE_MAP);
}
return _dependencies;
@@ -1196,6 +1203,9 @@ void RadiantSelectionSystem::initialiseModule(const ApplicationContext& ctx)
camGroup.registerMouseTool(std::make_shared<ui::DragSelectionMouseToolFaceOnly>());
camGroup.registerMouseTool(std::make_shared<ui::CycleSelectionMouseTool>());
camGroup.registerMouseTool(std::make_shared<ui::CycleSelectionMouseToolFaceOnly>());
+
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &RadiantSelectionSystem::onMapEvent));
}
void RadiantSelectionSystem::shutdownModule()
@@ -1210,7 +1220,7 @@ void RadiantSelectionSystem::shutdownModule()
destroyStatic();
}
-void RadiantSelectionSystem::checkComponentModeSelectionMode(const Selectable& selectable)
+void RadiantSelectionSystem::checkComponentModeSelectionMode(const ISelectable& selectable)
{
// This seems to be a fail-safe method, to detect situations where component mode is still
// active without any primitive selected - in which case the method exits component mode.
@@ -1481,5 +1491,14 @@ void RadiantSelectionSystem::deselectCmd(const cmd::ArgumentList& args)
}
}
+void RadiantSelectionSystem::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloading || ev == IMap::MapLoading)
+ {
+ setSelectedAll(false);
+ setSelectedAllComponents(false);
+ }
+}
+
// Define the static SelectionSystem module
module::StaticModule<RadiantSelectionSystem> radiantSelectionSystemModule;
diff --git a/radiant/selection/RadiantSelectionSystem.h b/radiant/selection/RadiantSelectionSystem.h
index d396432..900e75a 100644
--- a/radiant/selection/RadiantSelectionSystem.h
+++ b/radiant/selection/RadiantSelectionSystem.h
@@ -3,7 +3,9 @@
#include "iregistry.h"
#include "irenderable.h"
#include "iselection.h"
+#include "iradiant.h"
#include "icommandsystem.h"
+#include "imap.h"
#include "selectionlib.h"
#include "math/Matrix4.h"
@@ -85,7 +87,7 @@ public:
private:
SelectionInfo _selectionInfo;
- sigc::signal<void, const Selectable&> _sigSelectionChanged;
+ sigc::signal<void, const ISelectable&> _sigSelectionChanged;
EManipulatorMode _defaultManipulatorMode;
EManipulatorMode _manipulatorMode;
@@ -138,7 +140,7 @@ public:
void pivotChanged() const;
- void pivotChangedSelection(const Selectable& selectable);
+ void pivotChangedSelection(const ISelectable& selectable);
void addObserver(Observer* observer);
void removeObserver(Observer* observer);
@@ -155,8 +157,8 @@ public:
std::size_t countSelected() const;
std::size_t countSelectedComponents() const;
- void onSelectedChanged(const scene::INodePtr& node, const Selectable& selectable);
- void onComponentSelection(const scene::INodePtr& node, const Selectable& selectable);
+ void onSelectedChanged(const scene::INodePtr& node, const ISelectable& selectable);
+ void onComponentSelection(const scene::INodePtr& node, const ISelectable& selectable);
SelectionChangedSignal signal_selectionChanged() const
{
@@ -210,15 +212,15 @@ public:
const selection::WorkZone& getWorkZone();
- void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const;
- void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const;
+ void renderSolid(RenderableCollector& collector, const VolumeTest& volume) const override;
+ void renderWireframe(RenderableCollector& collector, const VolumeTest& volume) const override;
- void setRenderSystem(const RenderSystemPtr& renderSystem)
+ void setRenderSystem(const RenderSystemPtr& renderSystem) override
{}
- bool isHighlighted() const
+ std::size_t getHighlightFlags() override
{
- return false; // never highlighted
+ return Highlight::NoHighlight; // never highlighted
}
const Matrix4& GetPivot2World() const;
@@ -227,10 +229,10 @@ public:
static void destroyStatic();
// RegisterableModule implementation
- virtual const std::string& getName() const;
- virtual const StringSet& getDependencies() const;
- virtual void initialiseModule(const ApplicationContext& ctx);
- virtual void shutdownModule();
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
+ virtual void shutdownModule() override;
protected:
// Called when the app is idle to recalculate the workzone (if necessary)
@@ -265,7 +267,11 @@ private:
void onManipulatorModeChanged();
void onComponentModeChanged();
- void checkComponentModeSelectionMode(const Selectable& selectable); // connects to the selection change signal
+ void checkComponentModeSelectionMode(const ISelectable& selectable); // connects to the selection change signal
+
+ void performPointSelection(const SelectablesList& candidates, EModifier modifier);
void deselectCmd(const cmd::ArgumentList& args);
+
+ void onMapEvent(IMap::MapEvent ev);
};
diff --git a/radiant/selection/SceneWalkers.h b/radiant/selection/SceneWalkers.h
index 3dae274..dc08c64 100644
--- a/radiant/selection/SceneWalkers.h
+++ b/radiant/selection/SceneWalkers.h
@@ -10,24 +10,6 @@
#include "editable.h"
#include "brush/BrushNode.h"
-// -------------- Helper functions -------------------------------------
-
-inline AABB Node_getPivotBounds(const scene::INodePtr& node) {
- Entity* entity = Node_getEntity(node);
- if (entity != NULL && (entity->getEntityClass()->isFixedSize() || !scene::hasChildPrimitives(node)))
- {
- EditablePtr editable = Node_getEditable(node);
- if (editable != NULL) {
- return AABB(node->localToWorld().getMultipliedBy(editable->getLocalPivot()).t().getVector3(), Vector3(0, 0, 0));
- }
- else {
- return node->worldAABB();
- }
- }
-
- return node->worldAABB();
-}
-
// ----------- The Walker Classes ------------------------------------------------
// Selects the visited component instances in the graph, according to the current component mode
diff --git a/radiant/selection/SelectionTest.cpp b/radiant/selection/SelectionTest.cpp
index 177adac..a28d47f 100644
--- a/radiant/selection/SelectionTest.cpp
+++ b/radiant/selection/SelectionTest.cpp
@@ -213,13 +213,13 @@ scene::INodePtr SelectionTestWalker::getParentGroupEntity(const scene::INodePtr&
bool SelectionTestWalker::entityIsWorldspawn(const scene::INodePtr& node)
{
- return node_is_worldspawn(node);
+ return Node_isWorldspawn(node);
}
void SelectionTestWalker::performSelectionTest(const scene::INodePtr& selectableNode,
const scene::INodePtr& nodeToBeTested)
{
- SelectablePtr selectable = Node_getSelectable(selectableNode);
+ ISelectablePtr selectable = Node_getSelectable(selectableNode);
if (selectable == NULL) return; // skip non-selectables
diff --git a/radiant/selection/Selectors.h b/radiant/selection/Selectors.h
index 1c195be..63f6f95 100644
--- a/radiant/selection/Selectors.h
+++ b/radiant/selection/Selectors.h
@@ -1,17 +1,16 @@
-#ifndef SELECTOR_H_
-#define SELECTOR_H_
+#pragma once
#include <map>
#include <set>
#include "iselectiontest.h"
#include "iselectable.h"
-typedef std::multimap<SelectionIntersection, Selectable*> SelectableSortedSet;
+typedef std::multimap<SelectionIntersection, ISelectable*> SelectableSortedSet;
// A simple set that gets filled after the SelectableSortedSet is populated.
// greebo: I used this to merge two SelectionPools (entities and primitives)
// with a preferred sorting (see RadiantSelectionSystem::Scene_TestSelect())
-typedef std::list<Selectable*> SelectablesList;
+typedef std::list<ISelectable*> SelectablesList;
/* greebo: The SelectionPool contains all the instances that come into question for a selection operation.
* It can be seen as some kind of stack that can be traversed through
@@ -25,12 +24,12 @@ class SelectionPool :
{
SelectableSortedSet _pool;
SelectionIntersection _intersection;
- Selectable* _selectable;
+ ISelectable* _selectable;
// A set of all current Selectable* candidates, to prevent double-insertions
// The iterator value points to an element in the SelectableSortedSet
// to allow for fast removals.
- typedef std::map<Selectable*, SelectableSortedSet::iterator> SelectablesMap;
+ typedef std::map<ISelectable*, SelectableSortedSet::iterator> SelectablesMap;
SelectablesMap _currentSelectables;
public:
@@ -39,7 +38,7 @@ public:
* tested against selection to notify the SelectionPool
* which Selectable we're talking about.
*/
- void pushSelectable(Selectable& selectable)
+ void pushSelectable(ISelectable& selectable)
{
_intersection = SelectionIntersection();
_selectable = &selectable;
@@ -69,7 +68,7 @@ public:
/** greebo: This makes sure that only valid Intersections get added, otherwise
* we would add Selectables that haven't passed the test.
*/
- void addSelectable(const SelectionIntersection& intersection, Selectable* selectable)
+ void addSelectable(const SelectionIntersection& intersection, ISelectable* selectable)
{
if (!intersection.valid()) return; // skip invalid intersections
@@ -126,13 +125,13 @@ public:
class BooleanSelector : public Selector {
bool _selected;
SelectionIntersection _intersection;
- Selectable* _selectable;
+ ISelectable* _selectable;
public:
BooleanSelector() : _selected(false), _selectable(NULL)
{
}
- void pushSelectable(Selectable& selectable)
+ void pushSelectable(ISelectable& selectable)
{
_intersection = SelectionIntersection();
_selectable = &selectable;
@@ -162,16 +161,16 @@ public:
class BestSelector : public Selector {
SelectionIntersection _intersection;
- Selectable* _selectable;
+ ISelectable* _selectable;
SelectionIntersection _bestIntersection;
- std::list<Selectable*> _bestSelectable;
+ std::list<ISelectable*> _bestSelectable;
public:
BestSelector() : _bestIntersection(SelectionIntersection()), _bestSelectable(0)
{
}
- void pushSelectable(Selectable& selectable)
+ void pushSelectable(ISelectable& selectable)
{
_intersection = SelectionIntersection();
_selectable = &selectable;
@@ -198,10 +197,8 @@ public:
assign_if_closer(_intersection, intersection);
}
- std::list<Selectable*>& best()
+ std::list<ISelectable*>& best()
{
return _bestSelectable;
}
};
-
-#endif /*SELECTOR_H_*/
diff --git a/radiant/selection/TransformationVisitors.cpp b/radiant/selection/TransformationVisitors.cpp
index 9fe088e..b713b1d 100644
--- a/radiant/selection/TransformationVisitors.cpp
+++ b/radiant/selection/TransformationVisitors.cpp
@@ -105,16 +105,13 @@ void ScaleSelected::visit(const scene::INodePtr& node) const {
transform->setType(TRANSFORM_PRIMITIVE);
transform->setScale(m_scale);
{
- EditablePtr editable = Node_getEditable(node);
- const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : Matrix4::getIdentity();
-
Vector3 parent_translation;
translation_for_pivoted_scale(
parent_translation,
m_scale,
m_world_pivot,
- node->localToWorld().getMultipliedBy(localPivot),
- transformNode->localToParent().getMultipliedBy(localPivot)
+ node->localToWorld(),
+ transformNode->localToParent()
);
transform->setTranslation(parent_translation);
diff --git a/radiant/selection/TranslateManipulator.cpp b/radiant/selection/TranslateManipulator.cpp
index cf3cb5a..706b4e6 100644
--- a/radiant/selection/TranslateManipulator.cpp
+++ b/radiant/selection/TranslateManipulator.cpp
@@ -149,7 +149,7 @@ void TranslateManipulator::testSelect(const render::View& view, const Matrix4& p
if(!selector.failed()) {
(*selector.begin()).second->setSelected(true);
} else {
- Selectable* selectable = NULL;
+ ISelectable* selectable = NULL;
if (registry::getValue<bool>(RKEY_TRANSLATE_CONSTRAINED)) {
// None of the shown arrows (or quad) has been selected, select an axis based on the precedence
diff --git a/radiant/selection/algorithm/CommandNotAvailableException.h b/radiant/selection/algorithm/CommandNotAvailableException.h
new file mode 100644
index 0000000..a142dfa
--- /dev/null
+++ b/radiant/selection/algorithm/CommandNotAvailableException.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <stdexcept>
+
+namespace selection
+{
+
+namespace algorithm
+{
+
+/**
+ * Exception thrown by some algorithm routines if the desired
+ * command cannot be executed due to the current state of the
+ * scenegraph, selection or other reasons.
+ */
+class CommandNotAvailableException :
+ public std::exception
+{
+private:
+ std::string _what;
+public:
+ CommandNotAvailableException(const std::string& msg) :
+ std::exception(),
+ _what(msg)
+ {}
+
+ virtual const char* what() const throw() override
+ {
+ return _what.c_str();
+ }
+
+ // Converts a function that is throwing a CommandNotAvailableException
+ // to one that returns false instead (true if no exception is thrown)
+ static bool ToBool(const std::function<void()>& func)
+ {
+ try
+ {
+ func();
+ return true;
+ }
+ catch (CommandNotAvailableException&)
+ {
+ return false;
+ }
+ }
+};
+
+}
+
+}
diff --git a/radiant/selection/algorithm/Entity.cpp b/radiant/selection/algorithm/Entity.cpp
index edc9a76..5462142 100644
--- a/radiant/selection/algorithm/Entity.cpp
+++ b/radiant/selection/algorithm/Entity.cpp
@@ -16,66 +16,131 @@
#include "map/Map.h"
#include "eclass.h"
-namespace selection {
- namespace algorithm {
+namespace selection
+{
+
+namespace algorithm
+{
const char* const GKEY_BIND_KEY("/defaults/bindKey");
-/**
- * greebo: This walker traverses a subgraph and changes the classname
- * of all selected entities to the one passed to the constructor.
- */
-class EntitySetClassnameSelected :
- public SelectionSystem::Visitor
+void setEntityKeyvalue(const scene::INodePtr& node, const std::string& key, const std::string& value)
{
- std::string _classname;
-
- // Entites are getting accumulated in this list and processed at destruction time
- mutable std::set<scene::INodePtr> _entities;
-public:
- EntitySetClassnameSelected(const std::string& classname) :
- _classname(classname)
- {}
-
- ~EntitySetClassnameSelected() {
- for (std::set<scene::INodePtr>::iterator i = _entities.begin();
- i != _entities.end(); ++i)
+ Entity* entity = Node_getEntity(node);
+
+ if (entity)
+ {
+ // Check if we have a func_static-style entity
+ std::string name = entity->getKeyValue("name");
+ std::string model = entity->getKeyValue("model");
+ bool isFuncType = (!name.empty() && name == model);
+
+ // Set the actual value
+ entity->setKeyValue(key, value);
+
+ // Check for name key changes of func_statics
+ if (isFuncType && key == "name")
{
- // "Rename" the entity, this deletes the old node and creates a new one
- scene::INodePtr newNode = changeEntityClassname(*i, _classname);
+ // Adapt the model key along with the name
+ entity->setKeyValue("model", value);
+ }
+ }
+ else if (Node_isPrimitive(node))
+ {
+ // We have a primitve node selected, check its parent
+ scene::INodePtr parent(node->getParent());
- // Select the new entity node
- Node_setSelected(newNode, true);
+ if (!parent) return;
+
+ Entity* parentEnt = Node_getEntity(parent);
+
+ if (parentEnt)
+ {
+ // We have child primitive of an entity selected, the change
+ // should go right into that parent entity
+ parentEnt->setKeyValue(key, value);
}
}
+}
- virtual void visit(const scene::INodePtr& node) const {
- // Check if we have an entity
- Entity* entity = Node_getEntity(node);
+void setEntityKeyvalue(const std::string& key, const std::string& value)
+{
+ if (key.empty()) return;
- if (entity != NULL && Node_isSelected(node)) {
- if (entity->getKeyValue("classname") != "worldspawn") {
- _entities.insert(node);
- }
- else {
- wxutil::Messagebox::ShowError(
- _("Cannot change classname of worldspawn entity."));
+ if (key == "name")
+ {
+ // Check the global namespace if this change is ok
+ scene::IMapRootNodePtr mapRoot = GlobalMapModule().getRoot();
+
+ if (mapRoot)
+ {
+ INamespacePtr nspace = mapRoot->getNamespace();
+
+ if (nspace && nspace->nameExists(value))
+ {
+ // name exists, cancel the change
+ throw std::runtime_error((boost::format(_("The name %s already exists in this map!")) % value).str());
}
}
}
-};
-void setEntityClassname(const std::string& classname) {
+ // Detect classname changes
+ if (key == "classname")
+ {
+ // Classname changes are handled in a special way
+ setEntityClassname(value);
+ return;
+ }
+
+ // Regular key change, set value on all selected entities
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ setEntityKeyvalue(node, key, value);
+ });
+}
- if (classname.empty()) {
- rError() << "Cannot set classname to an empty string!" << std::endl;
+void setEntityClassname(const std::string& classname)
+{
+ if (classname.empty())
+ {
+ wxutil::Messagebox::ShowError(_("Cannot set classname to an empty string."));
+ return;
}
- // greebo: instantiate a walker and traverse the current selection
- EntitySetClassnameSelected classnameSetter(classname);
- GlobalSelectionSystem().foreachSelected(classnameSetter);
+ if (classname == "worldspawn")
+ {
+ throw std::runtime_error(_("Cannot change classname to worldspawn."));
+ }
+
+ std::set<scene::INodePtr> entitiesToProcess;
+
+ // Collect all entities that should have their classname set
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ // Check if we have an entity
+ Entity* entity = Node_getEntity(node);
- // The destructor of the classNameSetter will rename the entities
+ if (entity != NULL && Node_isSelected(node))
+ {
+ if (!entity->isWorldspawn())
+ {
+ entitiesToProcess.insert(node);
+ }
+ else
+ {
+ throw std::runtime_error(_("Cannot change classname of worldspawn entity."));
+ }
+ }
+ });
+
+ for (const scene::INodePtr& node : entitiesToProcess)
+ {
+ // "Rename" the entity, this deletes the old node and creates a new one
+ scene::INodePtr newNode = changeEntityClassname(node, classname);
+
+ // Select the new entity node
+ Node_setSelected(newNode, true);
+ }
}
void bindEntities(const cmd::ArgumentList& args) {
@@ -281,5 +346,5 @@ scene::INodePtr createEntityFromSelection(const std::string& name, const Vector3
return node;
}
- } // namespace algorithm
+} // namespace algorithm
} // namespace selection
diff --git a/radiant/selection/algorithm/Entity.h b/radiant/selection/algorithm/Entity.h
index d6d2a41..74a4546 100644
--- a/radiant/selection/algorithm/Entity.h
+++ b/radiant/selection/algorithm/Entity.h
@@ -12,6 +12,16 @@ namespace algorithm
{
/**
+ * Applies the key/value combination to the currently selected entities.
+ * It's safe to set a "classname" key through this method.
+ * This doesn't open an UndoableCommand session, take care of this in the
+ * client code.
+ *
+ * Throws a std::runtime_error in case the keyvalue cannot be applied.
+ */
+void setEntityKeyvalue(const std::string& key, const std::string& value);
+
+/**
* greebo: Changes the classname of the currently selected entities.
*/
void setEntityClassname(const std::string& classname);
diff --git a/radiant/selection/algorithm/General.cpp b/radiant/selection/algorithm/General.cpp
index e4d2223..6482a44 100644
--- a/radiant/selection/algorithm/General.cpp
+++ b/radiant/selection/algorithm/General.cpp
@@ -16,6 +16,7 @@
#include "ui/texturebrowser/TextureBrowser.h"
#include "string/convert.h"
#include "selectionlib.h"
+#include "entitylib.h"
#include "SelectionPolicies.h"
#include "selection/SceneWalkers.h"
@@ -313,11 +314,20 @@ void showAllHidden(const cmd::ArgumentList& args) {
SceneChangeNotify();
}
+/**
+ * Invert Selection walker
+ * Worldspawn brushes and patches will be considered, unless
+ * entity selection mode is active.
+ * An entity with or without any child nodes will be considered.
+ * The worldspawn node itself will be ignored.
+ * func_static children will be ignored.
+ */
class InvertSelectionWalker :
public scene::NodeVisitor
{
+private:
SelectionSystem::EMode _mode;
- SelectablePtr _selectable;
+
public:
InvertSelectionWalker(SelectionSystem::EMode mode) :
_mode(mode)
@@ -325,44 +335,103 @@ public:
bool pre(const scene::INodePtr& node)
{
- // Ignore hidden nodes
+ // Ignore hidden nodes (including their whole subgraph)
if (!node->visible()) return false;
Entity* entity = Node_getEntity(node);
// Check if we have a selectable
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
- if (selectable != NULL)
+ if (selectable)
{
switch (_mode)
{
case SelectionSystem::eEntity:
- if (entity != NULL && entity->getKeyValue("classname") != "worldspawn")
+ // Only consider non-worldspawn entities
+ if (entity != nullptr && !entity->isWorldspawn())
{
- _selectable = selectable;
+ selectable->setSelected(!selectable->isSelected());
}
break;
case SelectionSystem::ePrimitive:
- _selectable = selectable;
+ // Never select the worldspawn entity
+ if (entity == nullptr || !entity->isWorldspawn())
+ {
+ selectable->setSelected(!selectable->isSelected());
+ }
break;
- case SelectionSystem::eComponent:
- // Check if we have a componentselectiontestable instance
- ComponentSelectionTestablePtr compSelTestable =
- Node_getComponentSelectionTestable(node);
-
- // Only add it to the list if the instance has components and is already selected
- if (compSelTestable != NULL && selectable->isSelected())
+ case SelectionSystem::eGroupPart:
+ // All child primitives can be selected (worldspawn entity is filtered out)
+ if (entity == nullptr && Node_isEntity(node->getParent()))
{
- _selectable = selectable;
+ selectable->setSelected(!selectable->isSelected());
}
break;
+ case SelectionSystem::eComponent:
+ break; // not handled here
+ }
+ }
+
+ // Determine whether we want to traverse child objects of entities
+ if (entity != nullptr)
+ {
+ if (_mode == SelectionSystem::eGroupPart)
+ {
+ // In group part mode, we want to traverse all entities but worldspawn
+ return !entity->isWorldspawn();
+ }
+ else if (_mode == SelectionSystem::eEntity)
+ {
+ // In Entity selection mode, we don't need to traverse entity subgraphs
+ // as we only want the parent entity
+ return false;
+ }
+
+ // In primitive mode, we want to traverse worldspawn only
+ return entity->isWorldspawn();
+ }
+
+ // We can traverse all non-entities by default
+ return true;
+ }
+};
+
+class InvertComponentSelectionWalker :
+ public scene::NodeVisitor
+{
+ SelectionSystem::EComponentMode _mode;
+ ComponentSelectionTestablePtr _selectable;
+public:
+ InvertComponentSelectionWalker(SelectionSystem::EComponentMode mode) :
+ _mode(mode)
+ {}
+
+ bool pre(const scene::INodePtr& node)
+ {
+ // Ignore hidden nodes
+ if (!node->visible()) return false;
+
+ Entity* entity = Node_getEntity(node);
+
+ // Check if we have a selectable
+ ISelectablePtr selectable = Node_getSelectable(node);
+
+ if (selectable != NULL)
+ {
+ // Check if we have a componentselectiontestable instance
+ ComponentSelectionTestablePtr compSelTestable =
+ Node_getComponentSelectionTestable(node);
+
+ // Only add it to the list if the instance has components and is already selected
+ if (compSelTestable && selectable->isSelected())
+ {
+ _selectable = compSelTestable;
}
}
// Do we have a groupnode? If yes, don't traverse the children
- if (entity != NULL && scene::hasChildPrimitives(node) &&
- entity->getKeyValue("classname") != "worldspawn")
+ if (entity != NULL && scene::hasChildPrimitives(node) && !entity->isWorldspawn())
{
// Don't traverse the children of this groupnode
return false;
@@ -373,17 +442,26 @@ public:
void post(const scene::INodePtr& node)
{
- if (_selectable != NULL)
+ if (_selectable)
{
- _selectable->invertSelected();
- _selectable = SelectablePtr();
+ _selectable->invertSelectedComponents(_mode);
+ _selectable.reset();
}
}
};
-void invertSelection(const cmd::ArgumentList& args) {
- InvertSelectionWalker walker(GlobalSelectionSystem().Mode());
- GlobalSceneGraph().root()->traverse(walker);
+void invertSelection(const cmd::ArgumentList& args)
+{
+ if (GlobalSelectionSystem().Mode() == SelectionSystem::eComponent)
+ {
+ InvertComponentSelectionWalker walker(GlobalSelectionSystem().ComponentMode());
+ GlobalSceneGraph().root()->traverse(walker);
+ }
+ else
+ {
+ InvertSelectionWalker walker(GlobalSelectionSystem().Mode());
+ GlobalSceneGraph().root()->traverse(walker);
+ }
}
void deleteSelection()
@@ -454,12 +532,12 @@ public:
return false;
}
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
// ignore worldspawn
Entity* entity = Node_getEntity(node);
if (entity != NULL) {
- if (entity->getKeyValue("classname") == "worldspawn") {
+ if (entity->isWorldspawn()) {
return true;
}
}
@@ -575,7 +653,7 @@ AABB getCurrentSelectionBounds()
GlobalSelectionSystem().foreachSelected([&] (const scene::INodePtr& node)
{
- bounds.includeAABB(Node_getPivotBounds(node));
+ bounds.includeAABB(node->worldAABB());
});
return bounds;
diff --git a/radiant/selection/algorithm/Group.cpp b/radiant/selection/algorithm/Group.cpp
index d6e7f07..6f22cf6 100644
--- a/radiant/selection/algorithm/Group.cpp
+++ b/radiant/selection/algorithm/Group.cpp
@@ -5,9 +5,11 @@
#include "igroupnode.h"
#include "imainframe.h"
#include "itextstream.h"
+#include "iselectiongroup.h"
#include "selectionlib.h"
#include "entitylib.h"
#include "map/Map.h"
+#include "scene/SelectableNode.h"
#include "wxutil/dialog/MessageBox.h"
#include "selection/algorithm/Entity.h"
@@ -107,7 +109,7 @@ void ParentPrimitivesToEntityWalker::reparent()
if (!scene::hasChildPrimitives(oldParent))
{
// Is empty, but make sure we're not removing the worldspawn
- if (node_is_worldspawn(oldParent)) continue;
+ if (Node_isWorldspawn(oldParent)) continue;
// Is empty now, remove it
scene::removeNodeFromParent(oldParent);
@@ -360,12 +362,12 @@ void mergeSelectedEntities(const cmd::ArgumentList& args)
scene::INodePtr newParent = walker.getFirstSelectedGroupNode();
// Gather all group nodes in the selection
- GroupNodeCollector walker;
- GlobalSelectionSystem().foreachSelected(walker);
+ GroupNodeCollector collector;
+ GlobalSelectionSystem().foreachSelected(collector);
// Traverse all group nodes using a ParentPrimitivesToEntityWalker
- for (GroupNodeCollector::GroupNodeList::const_iterator i = walker.getList().begin();
- i != walker.getList().end(); ++i)
+ for (GroupNodeCollector::GroupNodeList::const_iterator i = collector.getList().begin();
+ i != collector.getList().end(); ++i)
{
if (*i == newParent) continue;
@@ -375,7 +377,7 @@ void mergeSelectedEntities(const cmd::ArgumentList& args)
reparentor.reparent();
}
- rMessage() << walker.getList().size() << " group nodes merged." << std::endl;
+ rMessage() << collector.getList().size() << " group nodes merged." << std::endl;
}
else
{
@@ -385,6 +387,131 @@ void mergeSelectedEntities(const cmd::ArgumentList& args)
}
}
+void checkGroupSelectedAvailable()
+{
+ if (GlobalSelectionSystem().Mode() != SelectionSystem::ePrimitive)
+ {
+ throw CommandNotAvailableException(_("Groups can be formed in Primitive selection mode only"));
+ }
+
+ if (GlobalSelectionSystem().getSelectionInfo().totalCount == 0)
+ {
+ throw CommandNotAvailableException(_("Nothing selected, cannot group anything"));
+ }
+
+ if (GlobalSelectionSystem().getSelectionInfo().totalCount == 1)
+ {
+ throw CommandNotAvailableException(_("Select more than one element to form a group"));
+ return;
+ }
+
+ // Check if the current selection already is member of the same group
+ std::set<std::size_t> groupIds;
+ bool hasUngroupedNode = false;
+
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ if (!selectable) return;
+
+ if (!selectable->getGroupIds().empty())
+ {
+ groupIds.insert(selectable->getMostRecentGroupId());
+ }
+ else
+ {
+ hasUngroupedNode = true;
+ }
+ });
+
+ if (!hasUngroupedNode && groupIds.size() == 1)
+ {
+ throw CommandNotAvailableException(_("The selected elements already form a group"));
+ }
+}
+
+void groupSelected()
+{
+ // This will throw exceptions
+ checkGroupSelectedAvailable();
+
+ UndoableCommand cmd("GroupSelected");
+
+ ISelectionGroupPtr group = GlobalSelectionGroupManager().createSelectionGroup();
+
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ group->addNode(node);
+ });
+
+ GlobalMainFrame().updateAllWindows();
+}
+
+void checkUngroupSelectedAvailable()
+{
+ if (GlobalSelectionSystem().Mode() != SelectionSystem::ePrimitive)
+ {
+ throw CommandNotAvailableException(_("Groups can be dissolved in Primitive selection mode only"));
+ }
+
+ if (GlobalSelectionSystem().getSelectionInfo().totalCount == 0)
+ {
+ throw CommandNotAvailableException(_("Nothing selected, cannot un-group anything"));
+ }
+
+ // Check if the current selection already is member of the same group
+ bool hasOnlyUngroupedNodes = true;
+
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ if (!selectable) return;
+
+ if (!selectable->getGroupIds().empty())
+ {
+ hasOnlyUngroupedNodes = false;
+ }
+ });
+
+ if (hasOnlyUngroupedNodes)
+ {
+ throw CommandNotAvailableException(_("The selected elements aren't part of any group"));
+ }
+}
+
+void ungroupSelected()
+{
+ // Will throw exceptions if not available
+ checkUngroupSelectedAvailable();
+
+ UndoableCommand cmd("UngroupSelected");
+
+ // Collect all the latest group Ids from all selected nodes
+ std::set<std::size_t> ids;
+
+ GlobalSelectionSystem().foreachSelected([&](const scene::INodePtr& node)
+ {
+ std::shared_ptr<scene::SelectableNode> selectable = std::dynamic_pointer_cast<scene::SelectableNode>(node);
+
+ if (!selectable) return;
+
+ if (selectable->isGroupMember())
+ {
+ ids.insert(selectable->getMostRecentGroupId());
+ }
+ });
+
+ // Now remove the found group by ID (maybe convert them to a selection set before removal?)
+ std::for_each(ids.begin(), ids.end(), [](std::size_t id)
+ {
+ GlobalSelectionGroupManager().deleteSelectionGroup(id);
+ });
+
+ GlobalMainFrame().updateAllWindows();
+}
+
} // namespace algorithm
} // namespace selection
diff --git a/radiant/selection/algorithm/Group.h b/radiant/selection/algorithm/Group.h
index cd82f50..c86246b 100644
--- a/radiant/selection/algorithm/Group.h
+++ b/radiant/selection/algorithm/Group.h
@@ -1,10 +1,10 @@
-#ifndef SELECTIONGROUP_H_
-#define SELECTIONGROUP_H_
+#pragma once
#include "icommandsystem.h"
#include "iselection.h"
#include "inode.h"
#include <list>
+#include "CommandNotAvailableException.h"
namespace selection {
namespace algorithm {
@@ -137,7 +137,29 @@ namespace selection {
*/
void mergeSelectedEntities(const cmd::ArgumentList& args);
+ /**
+ * Groups the currently selected elements.
+ * Will throw a CommandNotAvailableException if it cannot execute.
+ */
+ void groupSelected();
+
+ /**
+ * Returns if the groupSelected command is able to execute
+ * at this point, otherwise throws a CommandNotAvailableException
+ */
+ void checkGroupSelectedAvailable();
+
+ /**
+ * Resolve the currently selected group.
+ * Will throw a CommandNotAvailableException if it cannot execute.
+ */
+ void ungroupSelected();
+
+ /**
+ * Returns if the ungroupSelected command is able to execute
+ * at this point, otherwise throws a CommandNotAvailableException.
+ */
+ void checkUngroupSelectedAvailable();
+
} // namespace algorithm
} // namespace selection
-
-#endif /*SELECTIONGROUP_H_*/
diff --git a/radiant/selection/algorithm/GroupCycle.cpp b/radiant/selection/algorithm/GroupCycle.cpp
index 877f8d0..7fe3881 100644
--- a/radiant/selection/algorithm/GroupCycle.cpp
+++ b/radiant/selection/algorithm/GroupCycle.cpp
@@ -21,7 +21,7 @@ namespace algorithm {
{}
bool pre(const scene::INodePtr& node) {
- SelectablePtr selectable = Node_getSelectable(node);
+ ISelectablePtr selectable = Node_getSelectable(node);
// If a visible selectable was found and the path depth is appropriate, add it
if (selectable != NULL && node->visible()) {
diff --git a/radiant/selection/algorithm/Patch.cpp b/radiant/selection/algorithm/Patch.cpp
index d515d58..28a1519 100644
--- a/radiant/selection/algorithm/Patch.cpp
+++ b/radiant/selection/algorithm/Patch.cpp
@@ -83,17 +83,6 @@ void capPatch(const cmd::ArgumentList& args)
createPatchCaps(GlobalTextureBrowser().getSelectedShader());
}
-void cyclePatchProjection(const cmd::ArgumentList& args)
-{
- UndoableCommand undo("patchCycleUVProjectionAxis");
-
- GlobalSelectionSystem().foreachPatch([&] (Patch& patch) { patch.ProjectTexture(Patch::m_CycleCapIndex); });
-
- Patch::m_CycleCapIndex = (Patch::m_CycleCapIndex == 0) ? 1 : (Patch::m_CycleCapIndex == 1) ? 2 : 0;
-
- SceneChangeNotify();
-}
-
void insertPatchColumnsAtEnd(const cmd::ArgumentList& args)
{
UndoableCommand undo("patchInsertColumnsAtEnd");
diff --git a/radiant/selection/algorithm/Patch.h b/radiant/selection/algorithm/Patch.h
index 4c4dae5..ac556ff 100644
--- a/radiant/selection/algorithm/Patch.h
+++ b/radiant/selection/algorithm/Patch.h
@@ -18,8 +18,6 @@ void transposePatch(const cmd::ArgumentList& args);
void capPatch(const cmd::ArgumentList& args);
-void cyclePatchProjection(const cmd::ArgumentList& args);
-
void insertPatchColumnsAtEnd(const cmd::ArgumentList& args);
void insertPatchColumnsAtBeginning(const cmd::ArgumentList& args);
void insertPatchRowsAtEnd(const cmd::ArgumentList& args);
diff --git a/radiant/selection/algorithm/Primitives.cpp b/radiant/selection/algorithm/Primitives.cpp
index 6592781..eafa124 100644
--- a/radiant/selection/algorithm/Primitives.cpp
+++ b/radiant/selection/algorithm/Primitives.cpp
@@ -326,8 +326,8 @@ public:
patch->FlipTexture(1);
// Insert the patch into worldspawn
- scene::INodePtr worldSpawnNode = GlobalMap().getWorldspawn();
- assert(worldSpawnNode != NULL); // This must be non-NULL, otherwise we won't have faces
+ scene::INodePtr worldSpawnNode = GlobalMap().findOrInsertWorldspawn();
+ assert(worldSpawnNode); // This must be non-NULL, otherwise we won't have faces
worldSpawnNode->addChildNode(patchNode);
diff --git a/radiant/selection/algorithm/Transformation.cpp b/radiant/selection/algorithm/Transformation.cpp
index 127ee48..ffabb31 100644
--- a/radiant/selection/algorithm/Transformation.cpp
+++ b/radiant/selection/algorithm/Transformation.cpp
@@ -11,6 +11,7 @@
#include "iselection.h"
#include "imainframe.h"
#include "itextstream.h"
+#include "iselectiongroup.h"
#include "scenelib.h"
#include "registry/registry.h"
@@ -79,6 +80,10 @@ private:
// A container, which temporarily holds the cloned nodes
std::shared_ptr<scene::BasicRootNode> _cloneRoot;
+ // Map group IDs in this selection to new groups
+ typedef std::map<std::size_t, ISelectionGroupPtr> GroupMap;
+ GroupMap _groupMap;
+
public:
SelectionCloner() :
_cloneRoot(new scene::BasicRootNode)
@@ -122,21 +127,60 @@ public:
// Insert this node in the root
_cloneRoot->addChildNode(clone);
+
+ // Collect and add the group IDs of the source node
+ std::shared_ptr<IGroupSelectable> groupSelectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ if (groupSelectable)
+ {
+ const IGroupSelectable::GroupIds& groupIds = groupSelectable->getGroupIds();
+
+ // Get the Groups the source node was assigned to, and add the
+ // cloned node to the mapped group, one by one, keeping the order intact
+ for (std::size_t id : groupIds)
+ {
+ // Try to insert the ID, ignore if already exists
+ // Get a new mapping for the given group ID
+ const ISelectionGroupPtr& mappedGroup = getMappedGroup(id);
+
+ // Assign the new group ID to this clone
+ mappedGroup->addNode(clone);
+ }
+ }
+ }
+ }
+
+ // Gets the replacement ID for the given group ID
+ const ISelectionGroupPtr& getMappedGroup(std::size_t id)
+ {
+ std::pair<GroupMap::iterator, bool> found = _groupMap.insert(GroupMap::value_type(id, ISelectionGroupPtr()));
+
+ if (!found.second)
+ {
+ // We already covered this ID, return the mapped group
+ return found.first->second;
}
+
+ // Insertion was successful, so we didn't cover this ID yet
+ found.first->second = GlobalSelectionGroupManager().createSelectionGroup();
+
+ return found.first->second;
}
// Adds the cloned nodes to their designated parents. Pass TRUE to select the nodes.
- void moveClonedNodes(bool select) {
- for (Map::iterator i = _cloned.begin(); i != _cloned.end(); ++i)
+ void moveClonedNodes(bool select)
+ {
+ for (Map::value_type pair : _cloned)
{
// Remove the child from the basic container first
- _cloneRoot->removeChildNode(i->first);
+ _cloneRoot->removeChildNode(pair.first);
// Add the node to its parent
- i->second->addChildNode(i->first);
+ pair.second->addChildNode(pair.first);
- if (select) {
- Node_setSelected(i->first, true);
+ if (select)
+ {
+ Node_setSelected(pair.first, true);
}
}
}
@@ -151,9 +195,6 @@ void cloneSelected(const cmd::ArgumentList& args)
UndoableCommand undo("cloneSelected");
- // Create the list that will take the cloned instances
- SelectionCloner::Map cloned;
-
SelectionCloner cloner;
GlobalSceneGraph().root()->traverse(cloner);
@@ -321,6 +362,12 @@ void moveSelectedCmd(const cmd::ArgumentList& args)
return;
}
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("moveSelectionVertically");
std::string arg = boost::algorithm::to_lower_copy(args[0].getString());
@@ -417,18 +464,36 @@ void rotateSelectionAboutAxis(axis_t axis, float deg)
void rotateSelectionX(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("rotateSelected -axis x -angle -90");
rotateSelectionAboutAxis(eAxisX, -90);
}
void rotateSelectionY(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("rotateSelected -axis y -angle 90");
rotateSelectionAboutAxis(eAxisY, 90);
}
void rotateSelectionZ(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("rotateSelected -axis z -angle -90");
rotateSelectionAboutAxis(eAxisZ, -90);
}
@@ -443,18 +508,36 @@ void mirrorSelection(int axis)
void mirrorSelectionX(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("mirrorSelected -axis x");
mirrorSelection(0);
}
void mirrorSelectionY(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("mirrorSelected -axis y");
mirrorSelection(1);
}
void mirrorSelectionZ(const cmd::ArgumentList& args)
{
+ if (GlobalSelectionSystem().countSelected() == 0)
+ {
+ rMessage() << "Nothing selected." << std::endl;
+ return;
+ }
+
UndoableCommand undo("mirrorSelected -axis z");
mirrorSelection(2);
}
diff --git a/radiant/selection/group/SelectionGroup.h b/radiant/selection/group/SelectionGroup.h
new file mode 100644
index 0000000..b8f18a8
--- /dev/null
+++ b/radiant/selection/group/SelectionGroup.h
@@ -0,0 +1,120 @@
+#pragma once
+
+#include "iselectiongroup.h"
+#include "util/ScopedBoolLock.h"
+
+namespace selection
+{
+
+// Represents a named group of selectable items
+class SelectionGroup :
+ public ISelectionGroup
+{
+private:
+ std::size_t _id;
+
+ std::string _name;
+
+ // The contained nodes of this group
+ std::set<scene::INodeWeakPtr, std::owner_less<scene::INodeWeakPtr> > _nodes;
+
+ // To avoid entering feedback loops during group updates
+ bool _selectionLock;
+
+public:
+ SelectionGroup(std::size_t id) :
+ _id(id),
+ _selectionLock(false)
+ {}
+
+ std::size_t getId() const override
+ {
+ return _id;
+ }
+
+ const std::string& getName() const override
+ {
+ return _name;
+ }
+
+ void setName(const std::string& name) override
+ {
+ _name = name;
+ }
+
+ void addNode(const scene::INodePtr& node) override
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ if (!selectable) return;
+
+ selectable->addToGroup(_id);
+
+ _nodes.insert(scene::INodeWeakPtr(node));
+ }
+
+ void removeNode(const scene::INodePtr& node) override
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ assert(selectable);
+
+ selectable->removeFromGroup(_id);
+
+ _nodes.erase(scene::INodeWeakPtr(node));
+ }
+
+ void removeAllNodes()
+ {
+ foreachNode([this](const scene::INodePtr& node)
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ assert(selectable);
+
+ selectable->removeFromGroup(_id);
+ });
+ }
+
+ std::size_t size() const
+ {
+ return _nodes.size();
+ }
+
+ void setSelected(bool selected) override
+ {
+ // In debug build's, I'd like to see the feedback loops,
+ // so fire the debugger if we're re-entering the setSelected loop
+ assert(!_selectionLock);
+
+ if (_selectionLock) return; // already updating this group
+
+ util::ScopedBoolLock lock(_selectionLock);
+
+ foreachNode([&](const scene::INodePtr& node)
+ {
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ assert(selectable);
+
+ // Set the node status, but don't do a group update (we're already here)
+ selectable->setSelected(selected, false);
+ });
+ }
+
+ void foreachNode(const std::function<void(const scene::INodePtr&)>& functor) override
+ {
+ for (const scene::INodeWeakPtr& node : _nodes)
+ {
+ scene::INodePtr locked = node.lock();
+
+ if (locked)
+ {
+ functor(locked);
+ }
+ }
+ }
+};
+typedef std::shared_ptr<SelectionGroup> SelectionGroupPtr;
+
+} // namespace
diff --git a/radiant/selection/group/SelectionGroupInfoFileModule.cpp b/radiant/selection/group/SelectionGroupInfoFileModule.cpp
new file mode 100644
index 0000000..6f96e5e
--- /dev/null
+++ b/radiant/selection/group/SelectionGroupInfoFileModule.cpp
@@ -0,0 +1,342 @@
+#include "SelectionGroupInfoFileModule.h"
+
+#include <limits>
+#include "iselectiongroup.h"
+#include "ientity.h"
+#include "string/convert.h"
+#include <boost/algorithm/string/replace.hpp>
+#include "parser/DefTokeniser.h"
+
+#include "scenelib.h"
+#include "debugging/ScenegraphUtils.h"
+#include "SelectionGroupManager.h"
+
+namespace selection
+{
+
+namespace
+{
+ const char* const SELECTION_GROUPS = "SelectionGroups";
+ const char* const SELECTION_GROUP = "SelectionGroup";
+ const char* const NODE_MAPPING = "SelectionGroupNodeMapping";
+ const char* const NODE = "Node";
+ std::size_t EMPTY_PRIMITVE_NUM = std::numeric_limits<std::size_t>::max();
+}
+
+std::string SelectionGroupInfoFileModule::getName()
+{
+ return "Selection Groups";
+}
+
+void SelectionGroupInfoFileModule::onInfoFileSaveStart()
+{
+ _output.str(std::string());
+ _output.clear();
+ _nodeInfoCount = 0;
+}
+
+void SelectionGroupInfoFileModule::onSavePrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
+{
+ saveNode(node, entityNum, primitiveNum);
+}
+
+void SelectionGroupInfoFileModule::onSaveEntity(const scene::INodePtr& node, std::size_t entityNum)
+{
+ saveNode(node, entityNum, EMPTY_PRIMITVE_NUM);
+}
+
+void SelectionGroupInfoFileModule::saveNode(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
+{
+ // Don't export the group settings for models and particles, as they are not there
+ // at map load/parse time - these shouldn't even be passed in here
+ assert(Node_isEntity(node) || Node_isPrimitive(node));
+
+ std::shared_ptr<IGroupSelectable> selectable = std::dynamic_pointer_cast<IGroupSelectable>(node);
+
+ if (!selectable) return;
+
+ const IGroupSelectable::GroupIds& ids = selectable->getGroupIds();
+
+ // Ignore nodes that are not part of any group
+ if (ids.empty()) return;
+
+ // Node { ( EntityNum [PrimitiveNum] ) ( GroupId1 GroupId2 ... )
+ // e.g.
+ // Node { ( 3 78 ) ( 1 2 8 ) }
+
+ // Open a Node block
+ _output << "\t\t" << NODE << " { ";
+
+ // Write the node coordinates
+ _output << "( " << entityNum;
+
+ if (primitiveNum != EMPTY_PRIMITVE_NUM)
+ {
+ _output << " " << primitiveNum;
+ }
+
+ _output << " )";
+
+ _output << " ( ";
+
+ // Write a space-separated list of group IDs
+ for (const IGroupSelectable::GroupIds::value_type& i : ids)
+ {
+ _output << i << " ";
+ }
+
+ _output << ") ";
+
+ // Close the Node block
+ _output << "}";
+
+ // Write additional node info, for easier debugging in case of issues
+ _output << " // " << getNodeInfo(node);
+
+ _output << std::endl;
+
+ _nodeInfoCount++;
+}
+
+void SelectionGroupInfoFileModule::writeBlocks(std::ostream& stream)
+{
+ // Selection Group output
+ stream << "\t" << SELECTION_GROUPS << std::endl;
+
+ stream << "\t{" << std::endl;
+
+ // SelectionGroup 0 { Name of this group }
+
+ std::size_t selectionGroupCount = 0;
+
+ getSelectionGroupManagerInternal().foreachSelectionGroup([&] (ISelectionGroup& group)
+ {
+ // Ignore empty groups
+ if (group.size() == 0) return;
+
+ // Make sure to escape the quotes of the set name, use the XML quote entity
+ stream << "\t\t" << SELECTION_GROUP << " " << group.getId()
+ << " { \"" << boost::algorithm::replace_all_copy(group.getName(), "\"", """) << "\" }"
+ << std::endl;
+
+ selectionGroupCount++;
+ });
+
+ stream << "\t}" << std::endl;
+
+ rMessage() << selectionGroupCount << " selection groups exported." << std::endl;
+
+ // Write the NodeToLayerMapping block
+ stream << "\t" << NODE_MAPPING << std::endl;
+ stream << "\t{" << std::endl;
+
+ // Write the output buffer to the stream
+ stream << _output.str();
+
+ // Closing braces of NodeToLayerMapping block
+ stream << "\t}" << std::endl;
+
+ rMessage() << _nodeInfoCount << " selection group member mappings written." << std::endl;
+}
+
+void SelectionGroupInfoFileModule::onInfoFileSaveFinished()
+{
+ _output.str(std::string());
+ _output.clear();
+ _nodeInfoCount = 0;
+}
+
+void SelectionGroupInfoFileModule::onInfoFileLoadStart()
+{
+ _groupInfo.clear();
+ _nodeMapping.clear();
+}
+
+bool SelectionGroupInfoFileModule::canParseBlock(const std::string& blockName)
+{
+ return blockName == SELECTION_GROUPS || blockName == NODE_MAPPING;
+}
+
+void SelectionGroupInfoFileModule::parseBlock(const std::string& blockName, parser::DefTokeniser& tok)
+{
+ assert(canParseBlock(blockName));
+
+ if (blockName == SELECTION_GROUPS)
+ {
+ parseSelectionGroups(tok);
+ }
+ else if (blockName == NODE_MAPPING)
+ {
+ parseNodeMappings(tok);
+ }
+}
+
+void SelectionGroupInfoFileModule::parseSelectionGroups(parser::DefTokeniser& tok)
+{
+ // The opening brace
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == SELECTION_GROUP)
+ {
+ // SelectionGroup 0 { Name of this group }
+
+ // Get the ID
+ std::string idStr = tok.nextToken();
+ std::size_t id = string::convert<std::size_t>(idStr);
+
+ tok.assertNextToken("{");
+
+ std::string name = tok.nextToken();
+
+ tok.assertNextToken("}");
+
+ _groupInfo.push_back(SelectionGroupImportInfo());
+ _groupInfo.back().id = id;
+ _groupInfo.back().name = name;
+
+ rMessage() << "[InfoFile]: Parsed group #" << id << " with name \"" << name << "\"" << std::endl;
+
+ continue;
+ }
+
+ if (token == "}")
+ {
+ break;
+ }
+ }
+}
+
+void SelectionGroupInfoFileModule::parseNodeMappings(parser::DefTokeniser& tok)
+{
+ // The opening brace
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == NODE)
+ {
+ // Node { ( 3 78 ) ( 1 2 8 ) }
+
+ // Get the node coordinates
+ tok.assertNextToken("{");
+
+ tok.assertNextToken("(");
+
+ // Entity number is always there
+ std::size_t entityNum = string::convert<std::size_t>(tok.nextToken());
+ std::size_t primitiveNum = EMPTY_PRIMITVE_NUM;
+
+ token = tok.nextToken();
+
+ // If we hit the closing parenthesis, we don't have a primitive number
+ if (token != ")")
+ {
+ // We have a primitive number
+ primitiveNum = string::convert<std::size_t>(token);
+ tok.assertNextToken(")");
+ }
+
+ // Initialise the node mapping with an empty list
+ NodeMapping::iterator mapped = _nodeMapping.insert(NodeMapping::value_type(
+ map::NodeIndexPair(entityNum, primitiveNum),
+ IGroupSelectable::GroupIds())).first;
+
+ tok.assertNextToken("(");
+
+ // Parse the group IDs until we hit the closing parenthesis
+ for (token = tok.nextToken(); token != ")"; token = tok.nextToken())
+ {
+ std::size_t groupId = string::convert<std::size_t>(token);
+
+ mapped->second.push_back(groupId);
+ }
+
+ // Node closed
+ tok.assertNextToken("}");
+
+ continue;
+ }
+
+ if (token == "}")
+ {
+ break;
+ }
+ }
+}
+
+void SelectionGroupInfoFileModule::applyInfoToScene(const scene::IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap)
+{
+ // Remove all selection sets, there shouldn't be any left at this point
+ GlobalSelectionGroupManager().deleteAllSelectionGroups();
+
+ typedef std::map<std::size_t, ISelectionGroupPtr> GroupMap;
+ GroupMap groups;
+
+ // Re-construct the groups first
+ for (const SelectionGroupImportInfo& info : _groupInfo)
+ {
+ try
+ {
+ // Create the group by ID
+ ISelectionGroupPtr group = getSelectionGroupManagerInternal().createSelectionGroupInternal(info.id);
+ group->setName(info.name);
+
+ // Store for later retrieval
+ groups[info.id] = group;
+ }
+ catch (std::runtime_error& ex)
+ {
+ rError() << ex.what() << std::endl;
+ }
+ }
+
+ // Assign the nodes, as found in the mapping, keeping the group ID order intact
+ std::size_t failedNodes = 0;
+
+ for (const NodeMapping::value_type& mapping : _nodeMapping)
+ {
+ map::NodeIndexMap::const_iterator foundNode = nodeMap.find(mapping.first);
+
+ if (foundNode != nodeMap.end())
+ {
+ // Assign this node to its groups, following the order
+ for (const IGroupSelectable::GroupIds::value_type& id : mapping.second)
+ {
+ // Get the group and assign the node
+ GroupMap::iterator found = groups.find(id);
+
+ if (found == groups.end())
+ {
+ rWarning() << "Invalid group ID " << id << " encountered for node (" <<
+ mapping.first.first << "," << mapping.first.second << ")" << std::endl;
+ continue;
+ }
+
+ found->second->addNode(foundNode->second);
+ }
+ }
+ else
+ {
+ failedNodes++;
+ }
+ }
+
+ if (failedNodes > 0)
+ {
+ rWarning() << "Couldn't resolve " << failedNodes << " nodes in group mapping " << std::endl;
+ }
+}
+
+void SelectionGroupInfoFileModule::onInfoFileLoadFinished()
+{
+ _groupInfo.clear();
+ _nodeMapping.clear();
+}
+
+}
diff --git a/radiant/selection/group/SelectionGroupInfoFileModule.h b/radiant/selection/group/SelectionGroupInfoFileModule.h
new file mode 100644
index 0000000..c916dfc
--- /dev/null
+++ b/radiant/selection/group/SelectionGroupInfoFileModule.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <sstream>
+#include "iselectiongroup.h"
+#include "imapinfofile.h"
+
+namespace selection
+{
+
+/**
+ * Info file module importing/exporting the selection group info
+ * to the .darkradiant file of persistence between mapping sessions.
+ */
+class SelectionGroupInfoFileModule :
+ public map::IMapInfoFileModule
+{
+private:
+ struct SelectionGroupImportInfo
+ {
+ // Group ID
+ std::size_t id;
+
+ // The name of this group
+ std::string name;
+ };
+
+ // Parsed selection group information
+ std::vector<SelectionGroupImportInfo> _groupInfo;
+
+ // Parsed node mapping
+ typedef std::map<map::NodeIndexPair, IGroupSelectable::GroupIds> NodeMapping;
+ NodeMapping _nodeMapping;
+
+ std::stringstream _output;
+
+ std::size_t _nodeInfoCount;
+
+public:
+ std::string getName() override;
+
+ void onInfoFileSaveStart() override;
+ void onSavePrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum) override;
+ void onSaveEntity(const scene::INodePtr& node, std::size_t entityNum) override;
+ void writeBlocks(std::ostream& stream) override;
+ void onInfoFileSaveFinished() override;
+
+ void onInfoFileLoadStart() override;
+ bool canParseBlock(const std::string& blockName) override;
+ void parseBlock(const std::string& blockName, parser::DefTokeniser& tok) override;
+ void applyInfoToScene(const scene::IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap) override;
+ void onInfoFileLoadFinished() override;
+
+private:
+ void saveNode(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum);
+ void parseSelectionGroups(parser::DefTokeniser& tok);
+ void parseNodeMappings(parser::DefTokeniser& tok);
+};
+
+}
diff --git a/radiant/selection/group/SelectionGroupManager.cpp b/radiant/selection/group/SelectionGroupManager.cpp
new file mode 100644
index 0000000..28e2065
--- /dev/null
+++ b/radiant/selection/group/SelectionGroupManager.cpp
@@ -0,0 +1,280 @@
+#include "SelectionGroupManager.h"
+
+#include "i18n.h"
+#include "imap.h"
+#include "iradiant.h"
+#include "itextstream.h"
+#include "imapinfofile.h"
+#include "icommandsystem.h"
+#include "iselection.h"
+#include "ieventmanager.h"
+#include "imainframe.h"
+#include "iundo.h"
+#include "iorthocontextmenu.h"
+#include "modulesystem/StaticModule.h"
+#include "selection/algorithm/Group.h"
+
+#include "wxutil/dialog/MessageBox.h"
+#include "selectionlib.h"
+#include "SelectionGroup.h"
+#include "scene/SelectableNode.h"
+#include "SelectionGroupInfoFileModule.h"
+#include "wxutil/menu/MenuItem.h"
+#include "wxutil/menu/IconTextMenuItem.h"
+
+namespace selection
+{
+
+SelectionGroupManager::SelectionGroupManager() :
+ _nextGroupId(1)
+{}
+
+const std::string& SelectionGroupManager::getName() const
+{
+ static std::string _name(MODULE_SELECTIONGROUP);
+ return _name;
+}
+
+const StringSet& SelectionGroupManager::getDependencies() const
+{
+ static StringSet _dependencies;
+
+ if (_dependencies.empty())
+ {
+ _dependencies.insert(MODULE_SELECTIONSYSTEM);
+ _dependencies.insert(MODULE_EVENTMANAGER);
+ _dependencies.insert(MODULE_COMMANDSYSTEM);
+ _dependencies.insert(MODULE_RADIANT);
+ _dependencies.insert(MODULE_MAP);
+ _dependencies.insert(MODULE_MAPINFOFILEMANAGER);
+ }
+
+ return _dependencies;
+}
+
+void SelectionGroupManager::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << getName() << "::initialiseModule called." << std::endl;
+
+ GlobalCommandSystem().addCommand("GroupSelected",
+ std::bind(&SelectionGroupManager::groupSelectedCmd, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("UngroupSelected",
+ std::bind(&SelectionGroupManager::ungroupSelectedCmd, this, std::placeholders::_1));
+ GlobalCommandSystem().addCommand("DeleteAllSelectionGroups",
+ std::bind(&SelectionGroupManager::deleteAllSelectionGroupsCmd, this, std::placeholders::_1));
+
+ GlobalEventManager().addCommand("GroupSelected", "GroupSelected");
+ GlobalEventManager().addCommand("UngroupSelected", "UngroupSelected");
+ GlobalEventManager().addCommand("DeleteAllSelectionGroups", "DeleteAllSelectionGroups");
+
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &SelectionGroupManager::onMapEvent)
+ );
+
+ GlobalMapInfoFileManager().registerInfoFileModule(
+ std::make_shared<SelectionGroupInfoFileModule>()
+ );
+
+ GlobalRadiant().signal_radiantStarted().connect([this] ()
+ {
+ GlobalUIManager().getMenuManager().insert(
+ "main/edit/parent", "ungroupSelected", ui::eMenuItemType::menuItem, _("Ungroup Selection"), "ungroup_selection.png", "UngroupSelected");
+
+ GlobalUIManager().getMenuManager().insert(
+ "main/edit/ungroupSelected", "groupSelected", ui::eMenuItemType::menuItem, _("Group Selection"), "group_selection.png", "GroupSelected");
+
+ GlobalUIManager().getMenuManager().insert(
+ "main/edit/parent", "groupSelectedSeparator", ui::eMenuItemType::menuSeparator, "", "", "");
+ });
+
+ GlobalOrthoContextMenu().addItem(std::make_shared<wxutil::MenuItem>(
+ new wxutil::IconTextMenuItem(_("Group Selection"), "group_selection.png"),
+ []() { algorithm::groupSelected(); },
+ []() { return algorithm::CommandNotAvailableException::ToBool(algorithm::checkGroupSelectedAvailable); }),
+ ui::IOrthoContextMenu::SECTION_SELECTION_GROUPS);
+
+ GlobalOrthoContextMenu().addItem(std::make_shared<wxutil::MenuItem>(
+ new wxutil::IconTextMenuItem(_("Ungroup Selection"), "ungroup_selection.png"),
+ []() { algorithm::ungroupSelected(); },
+ []() { return algorithm::CommandNotAvailableException::ToBool(algorithm::checkUngroupSelectedAvailable); }),
+ ui::IOrthoContextMenu::SECTION_SELECTION_GROUPS);
+}
+
+void SelectionGroupManager::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloaded)
+ {
+ deleteAllSelectionGroups();
+ resetNextGroupId();
+ }
+}
+
+ISelectionGroupPtr SelectionGroupManager::createSelectionGroup()
+{
+ // Reserve a new group ID
+ std::size_t id = generateGroupId();
+
+ SelectionGroupPtr group = std::make_shared<SelectionGroup>(id);
+ _groups[id] = group;
+
+ return group;
+}
+
+ISelectionGroupPtr SelectionGroupManager::getSelectionGroup(std::size_t id)
+{
+ SelectionGroupMap::iterator found = _groups.find(id);
+
+ return found != _groups.end() ? found->second : ISelectionGroupPtr();
+}
+
+ISelectionGroupPtr SelectionGroupManager::findOrCreateSelectionGroup(std::size_t id)
+{
+ SelectionGroupMap::iterator found = _groups.find(id);
+
+ return found != _groups.end() ? found->second : createSelectionGroupInternal(id);
+}
+
+void SelectionGroupManager::setGroupSelected(std::size_t id, bool selected)
+{
+ SelectionGroupMap::iterator found = _groups.find(id);
+
+ if (found == _groups.end())
+ {
+ rError() << "Cannot find the group with ID " << id << std::endl;
+ return;
+ }
+
+ found->second->setSelected(selected);
+}
+
+void SelectionGroupManager::deleteSelectionGroup(std::size_t id)
+{
+ UndoableCommand cmd("DeleteSelectionGroup");
+
+ doDeleteSelectionGroup(id);
+}
+
+void SelectionGroupManager::doDeleteSelectionGroup(std::size_t id)
+{
+ SelectionGroupMap::iterator found = _groups.find(id);
+
+ if (found == _groups.end())
+ {
+ rError() << "Cannot delete the group with ID " << id << " as it doesn't exist." << std::endl;
+ return;
+ }
+
+ found->second->removeAllNodes();
+
+ _groups.erase(found);
+}
+
+void SelectionGroupManager::deleteAllSelectionGroups()
+{
+ UndoableCommand cmd("DeleteAllSelectionGroups");
+
+ for (SelectionGroupMap::iterator g = _groups.begin(); g != _groups.end(); )
+ {
+ doDeleteSelectionGroup((g++)->first);
+ }
+
+ assert(_groups.empty());
+}
+
+void SelectionGroupManager::foreachSelectionGroup(const std::function<void(ISelectionGroup&)>& func)
+{
+ for (SelectionGroupMap::value_type& pair : _groups)
+ {
+ func(*pair.second);
+ }
+}
+
+ISelectionGroupPtr SelectionGroupManager::createSelectionGroupInternal(std::size_t id)
+{
+ if (_groups.find(id) != _groups.end())
+ {
+ rWarning() << "Cannot create group with ID " << id << ", as it's already taken." << std::endl;
+ throw std::runtime_error("Group ID already taken");
+ }
+
+ SelectionGroupPtr group = std::make_shared<SelectionGroup>(id);
+ _groups[id] = group;
+
+ // Adjust the next group ID
+ resetNextGroupId();
+
+ return group;
+}
+
+void SelectionGroupManager::deleteAllSelectionGroupsCmd(const cmd::ArgumentList& args)
+{
+ deleteAllSelectionGroups();
+}
+
+void SelectionGroupManager::groupSelectedCmd(const cmd::ArgumentList& args)
+{
+ try
+ {
+ algorithm::groupSelected();
+ }
+ catch (selection::algorithm::CommandNotAvailableException& ex)
+ {
+ rError() << ex.what() << std::endl;
+ wxutil::Messagebox::ShowError(ex.what());
+ }
+}
+
+void SelectionGroupManager::ungroupSelectedCmd(const cmd::ArgumentList& args)
+{
+ try
+ {
+ algorithm::ungroupSelected();
+ }
+ catch (selection::algorithm::CommandNotAvailableException& ex)
+ {
+ rError() << ex.what() << std::endl;
+ wxutil::Messagebox::ShowError(ex.what());
+ }
+}
+
+void SelectionGroupManager::resetNextGroupId()
+{
+ if (_groups.empty())
+ {
+ _nextGroupId = 0;
+ }
+ else
+ {
+ _nextGroupId = _groups.rbegin()->first + 1;
+ }
+}
+
+std::size_t SelectionGroupManager::generateGroupId()
+{
+#if 0
+ for (std::size_t i = 0; i < std::numeric_limits<std::size_t>::max(); ++i)
+ {
+ if (_groups.find(i) == _groups.end())
+ {
+ // Found a free ID
+ return i;
+ }
+ }
+#endif
+
+ if (_nextGroupId + 1 == std::numeric_limits<std::size_t>::max())
+ {
+ throw std::runtime_error("Out of group IDs.");
+ }
+
+ return _nextGroupId++;
+}
+
+module::StaticModule<SelectionGroupManager> staticSelectionGroupManagerModule;
+
+SelectionGroupManager& getSelectionGroupManagerInternal()
+{
+ return *staticSelectionGroupManagerModule.getModule();
+}
+
+}
diff --git a/radiant/selection/group/SelectionGroupManager.h b/radiant/selection/group/SelectionGroupManager.h
new file mode 100644
index 0000000..471c2f0
--- /dev/null
+++ b/radiant/selection/group/SelectionGroupManager.h
@@ -0,0 +1,62 @@
+#pragma once
+
+#include "iselectiongroup.h"
+#include "imap.h"
+#include "icommandsystem.h"
+#include <map>
+
+namespace selection
+{
+
+class SelectionGroup;
+typedef std::shared_ptr<SelectionGroup> SelectionGroupPtr;
+
+class SelectionGroupManager :
+ public ISelectionGroupManager
+{
+private:
+ typedef std::map<std::size_t, SelectionGroupPtr> SelectionGroupMap;
+ SelectionGroupMap _groups;
+
+ // Group IDs are never re-used during the same mapping session
+ // to support undo/redo operations.
+ std::size_t _nextGroupId;
+
+public:
+ SelectionGroupManager();
+
+ const std::string& getName() const override;
+ const StringSet& getDependencies() const override;
+ void initialiseModule(const ApplicationContext& ctx) override;
+
+ ISelectionGroupPtr createSelectionGroup() override;
+ void setGroupSelected(std::size_t id, bool selected) override;
+ void deleteAllSelectionGroups() override;
+ void deleteSelectionGroup(std::size_t id) override;
+ ISelectionGroupPtr getSelectionGroup(std::size_t id) override;
+ ISelectionGroupPtr findOrCreateSelectionGroup(std::size_t id) override;
+
+ // Internal methods only accessible through getSelectionGroupManagerInternal()
+
+ void foreachSelectionGroup(const std::function<void(ISelectionGroup&)>& func);
+
+ // Internal method allowing to create groups by ID
+ ISelectionGroupPtr createSelectionGroupInternal(std::size_t id);
+
+private:
+ void deleteAllSelectionGroupsCmd(const cmd::ArgumentList& args);
+ void groupSelectedCmd(const cmd::ArgumentList& args);
+ void ungroupSelectedCmd(const cmd::ArgumentList& args);
+
+ void onMapEvent(IMap::MapEvent ev);
+
+ std::size_t generateGroupId();
+ void resetNextGroupId();
+
+ void doDeleteSelectionGroup(std::size_t id);
+};
+
+// Internal accessor method to get hold of the implementing subclass
+SelectionGroupManager& getSelectionGroupManagerInternal();
+
+}
diff --git a/radiant/selection/selectionset/SelectionSetInfoFileModule.cpp b/radiant/selection/selectionset/SelectionSetInfoFileModule.cpp
new file mode 100644
index 0000000..b78a59b
--- /dev/null
+++ b/radiant/selection/selectionset/SelectionSetInfoFileModule.cpp
@@ -0,0 +1,230 @@
+#include "SelectionSetInfoFileModule.h"
+
+#include <limits>
+#include "itextstream.h"
+#include "string/convert.h"
+#include <boost/algorithm/string/replace.hpp>
+#include "parser/DefTokeniser.h"
+
+namespace selection
+{
+
+namespace
+{
+ const char* const SELECTION_SETS = "SelectionSets";
+ const char* const SELECTION_SET = "SelectionSet";
+ std::size_t EMPTY_PRIMITVE_NUM = std::numeric_limits<std::size_t>::max();
+}
+
+std::string SelectionSetInfoFileModule::getName()
+{
+ return "Selection Set Mapping";
+}
+
+void SelectionSetInfoFileModule::onInfoFileSaveStart()
+{
+ _exportInfo.clear();
+
+ // Visit all selection sets and assemble the info into the structures
+ GlobalSelectionSetManager().foreachSelectionSet([&](const ISelectionSetPtr& set)
+ {
+ // Get all nodes of this selection set and store them for later use
+ _exportInfo.push_back(SelectionSetExportInfo());
+
+ _exportInfo.back().set = set;
+ _exportInfo.back().nodes = set->getNodes();
+ });
+}
+
+void SelectionSetInfoFileModule::onSavePrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum)
+{
+ // Determine the item index for the selection set index mapping
+ std::for_each(_exportInfo.begin(), _exportInfo.end(), [&](SelectionSetExportInfo& info)
+ {
+ if (info.nodes.find(node) != info.nodes.end())
+ {
+ info.nodeIndices.insert(map::NodeIndexPair(entityNum, primitiveNum));
+ }
+ });
+}
+
+void SelectionSetInfoFileModule::onSaveEntity(const scene::INodePtr& node, std::size_t entityNum)
+{
+ // Determine the item index for the selection set index mapping
+ std::for_each(_exportInfo.begin(), _exportInfo.end(), [&](SelectionSetExportInfo& info)
+ {
+ if (info.nodes.find(node) != info.nodes.end())
+ {
+ info.nodeIndices.insert(map::NodeIndexPair(entityNum, EMPTY_PRIMITVE_NUM));
+ }
+ });
+}
+
+void SelectionSetInfoFileModule::writeBlocks(std::ostream& stream)
+{
+ // Selection Set output
+ stream << "\t" << SELECTION_SETS << std::endl;
+
+ stream << "\t{" << std::endl;
+
+ std::size_t selectionSetCount = 0;
+
+ std::for_each(_exportInfo.begin(), _exportInfo.end(), [&](SelectionSetExportInfo& info)
+ {
+ std::string indices = "";
+
+ std::for_each(info.nodeIndices.begin(), info.nodeIndices.end(),
+ [&](const map::NodeIndexPair& pair)
+ {
+ if (pair.second == EMPTY_PRIMITVE_NUM)
+ {
+ // only entity number
+ indices += "( " + string::to_string(pair.first) + " ) ";
+ }
+ else
+ {
+ // entity & primitive number
+ indices += "( " + string::to_string(pair.first) + " " + string::to_string(pair.second) + " ) ";
+ }
+ });
+
+ // Make sure to escape the quotes of the set name, use the XML quote entity
+ stream << "\t\t" << SELECTION_SET << " " << selectionSetCount++
+ << " { \"" << boost::algorithm::replace_all_copy(info.set->getName(), "\"", """) << "\" } "
+ << " { " << indices << " } "
+ << std::endl;
+ });
+
+ stream << "\t}" << std::endl;
+
+ rMessage() << _exportInfo.size() << " selection sets exported." << std::endl;
+}
+
+void SelectionSetInfoFileModule::onInfoFileSaveFinished()
+{
+ _exportInfo.clear();
+}
+
+void SelectionSetInfoFileModule::onInfoFileLoadStart()
+{
+ _importInfo.clear();
+}
+
+bool SelectionSetInfoFileModule::canParseBlock(const std::string& blockName)
+{
+ return blockName == SELECTION_SETS;
+}
+
+void SelectionSetInfoFileModule::parseBlock(const std::string& blockName, parser::DefTokeniser& tok)
+{
+ if (blockName != SELECTION_SETS) return;
+
+ // SelectionSet 2 { "Stairs" } { (0 4076) (0 4077) (0 4078) (0 4079) (0 4309) (2) }
+
+ // The opening brace
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string token = tok.nextToken();
+
+ if (token == SELECTION_SET)
+ {
+ // Create a new SelectionSet info structure
+ _importInfo.push_back(SelectionSetImportInfo());
+
+ std::size_t selectionSetIndex = string::convert<std::size_t>(tok.nextToken());
+
+ rMessage() << "Parsing Selection Set #" << selectionSetIndex << std::endl;
+
+ tok.assertNextToken("{");
+
+ // Parse the name, replacing the " placeholder with a proper quote
+ _importInfo.back().name = boost::algorithm::replace_all_copy(tok.nextToken(), """, "\"");
+
+ tok.assertNextToken("}");
+
+ tok.assertNextToken("{");
+
+ while (tok.hasMoreTokens())
+ {
+ std::string nextToken = tok.nextToken();
+
+ if (nextToken == "}") break;
+
+ // If it's not a closing curly brace, it must be an opening parenthesis
+ if (nextToken != "(")
+ {
+ throw parser::ParseException("InfoFile: Assertion failed: Required \"("
+ "\", found \"" + nextToken + "\"");
+ }
+
+ // Expect one or two numbers now
+ std::size_t entityNum = string::convert<std::size_t>(tok.nextToken());
+
+ nextToken = tok.nextToken();
+
+ if (nextToken == ")")
+ {
+ // Just the entity number, no primitive number
+ _importInfo.back().nodeIndices.insert(
+ map::NodeIndexPair(entityNum, EMPTY_PRIMITVE_NUM));
+ }
+ else
+ {
+ // Primitive number is provided as well
+ std::size_t primitiveNum = string::convert<std::size_t>(nextToken);
+
+ // No more than 2 numbers are supported, so assume a closing parenthesis now
+ tok.assertNextToken(")");
+
+ _importInfo.back().nodeIndices.insert(
+ map::NodeIndexPair(entityNum, primitiveNum));
+ }
+ }
+ }
+
+ if (token == "}") break;
+ }
+}
+
+void SelectionSetInfoFileModule::applyInfoToScene(const scene::IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap)
+{
+ // Remove all selection sets, there shouldn't be any left at this point
+ GlobalSelectionSetManager().deleteAllSelectionSets();
+
+ // Re-construct the selection sets
+ std::for_each(_importInfo.begin(), _importInfo.end(), [&](const SelectionSetImportInfo& info)
+ {
+ ISelectionSetPtr set = GlobalSelectionSetManager().createSelectionSet(info.name);
+
+ std::size_t failedNodes = 0;
+
+ std::for_each(info.nodeIndices.begin(), info.nodeIndices.end(),
+ [&](const map::NodeIndexPair& indexPair)
+ {
+ map::NodeIndexMap::const_iterator i = nodeMap.find(indexPair);
+
+ if (i != nodeMap.end())
+ {
+ set->addNode(i->second);
+ }
+ else
+ {
+ failedNodes++;
+ }
+ });
+
+ if (failedNodes > 0)
+ {
+ rWarning() << "Couldn't resolve " << failedNodes << " nodes in selection set " << set->getName() << std::endl;
+ }
+ });
+}
+
+void SelectionSetInfoFileModule::onInfoFileLoadFinished()
+{
+ _importInfo.clear();
+}
+
+}
diff --git a/radiant/selection/selectionset/SelectionSetInfoFileModule.h b/radiant/selection/selectionset/SelectionSetInfoFileModule.h
new file mode 100644
index 0000000..e21cde4
--- /dev/null
+++ b/radiant/selection/selectionset/SelectionSetInfoFileModule.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "imapinfofile.h"
+#include "iselectionset.h"
+
+namespace selection
+{
+
+/**
+ * Info file module importing/exporting the selection set mapping
+ * to the .darkradiant file of persistence between mapping sessions.
+ */
+class SelectionSetInfoFileModule :
+ public map::IMapInfoFileModule
+{
+private:
+ struct SelectionSetImportInfo
+ {
+ // The name of this set
+ std::string name;
+
+ // The node indices, which will be resolved to nodes after import
+ std::set<map::NodeIndexPair> nodeIndices;
+ };
+
+ // Parsed selection set information
+ std::vector<SelectionSetImportInfo> _importInfo;
+
+ struct SelectionSetExportInfo
+ {
+ // The set we're working with
+ selection::ISelectionSetPtr set;
+
+ // The nodes in this set
+ std::set<scene::INodePtr> nodes;
+
+ // The node indices, which will be resolved during traversal
+ std::set<map::NodeIndexPair> nodeIndices;
+ };
+
+ // SelectionSet-related
+ typedef std::vector<SelectionSetExportInfo> SelectionSetInfo;
+ SelectionSetInfo _exportInfo;
+
+public:
+ std::string getName() override;
+
+ void onInfoFileSaveStart() override;
+ void onSavePrimitive(const scene::INodePtr& node, std::size_t entityNum, std::size_t primitiveNum) override;
+ void onSaveEntity(const scene::INodePtr& node, std::size_t entityNum) override;
+ void writeBlocks(std::ostream& stream) override;
+ void onInfoFileSaveFinished() override;
+
+ void onInfoFileLoadStart() override;
+ bool canParseBlock(const std::string& blockName) override;
+ void parseBlock(const std::string& blockName, parser::DefTokeniser& tok) override;
+ void applyInfoToScene(const scene::IMapRootNodePtr& root, const map::NodeIndexMap& nodeMap) override;
+ void onInfoFileLoadFinished() override;
+};
+
+}
diff --git a/radiant/selection/selectionset/SelectionSetManager.cpp b/radiant/selection/selectionset/SelectionSetManager.cpp
index 361b699..45491b7 100644
--- a/radiant/selection/selectionset/SelectionSetManager.cpp
+++ b/radiant/selection/selectionset/SelectionSetManager.cpp
@@ -1,15 +1,16 @@
#include "SelectionSetManager.h"
#include "itextstream.h"
-#include "iradiant.h"
#include "i18n.h"
#include "iselection.h"
#include "idialogmanager.h"
+#include "imapinfofile.h"
#include "iuimanager.h"
#include "ieventmanager.h"
#include "imainframe.h"
#include "modulesystem/StaticModule.h"
#include "SelectionSetToolmenu.h"
+#include "SelectionSetInfoFileModule.h"
#include <wx/toolbar.h>
#include <wx/frame.h>
@@ -48,6 +49,8 @@ const StringSet& SelectionSetManager::getDependencies() const
_dependencies.insert(MODULE_EVENTMANAGER);
_dependencies.insert(MODULE_COMMANDSYSTEM);
_dependencies.insert(MODULE_RADIANT);
+ _dependencies.insert(MODULE_MAP);
+ _dependencies.insert(MODULE_MAPINFOFILEMANAGER);
}
return _dependencies;
@@ -66,13 +69,30 @@ void SelectionSetManager::initialiseModule(const ApplicationContext& ctx)
std::bind(&SelectionSetManager::deleteAllSelectionSetsCmd, this, std::placeholders::_1));
GlobalEventManager().addCommand("DeleteAllSelectionSets", "DeleteAllSelectionSets");
+
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &SelectionSetManager::onMapEvent)
+ );
+
+ GlobalMapInfoFileManager().registerInfoFileModule(
+ std::make_shared<SelectionSetInfoFileModule>()
+ );
}
void SelectionSetManager::shutdownModule()
{
+ _sigSelectionSetsChanged.clear();
_selectionSets.clear();
}
+void SelectionSetManager::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloaded)
+ {
+ deleteAllSelectionSets();
+ }
+}
+
void SelectionSetManager::onRadiantStartup()
{
// Get the horizontal toolbar and add a custom widget
diff --git a/radiant/selection/selectionset/SelectionSetManager.h b/radiant/selection/selectionset/SelectionSetManager.h
index 25690aa..616a54a 100644
--- a/radiant/selection/selectionset/SelectionSetManager.h
+++ b/radiant/selection/selectionset/SelectionSetManager.h
@@ -2,6 +2,7 @@
#include "iselectionset.h"
#include "iradiant.h"
+#include "imap.h"
#include "icommandsystem.h"
#include <map>
@@ -53,6 +54,7 @@ public:
void deleteAllSelectionSetsCmd(const cmd::ArgumentList& args);
private:
+ void onMapEvent(IMap::MapEvent ev);
void onDeleteAllSetsClicked(wxCommandEvent& ev);
};
diff --git a/radiant/selection/shaderclipboard/ShaderClipboard.cpp b/radiant/selection/shaderclipboard/ShaderClipboard.cpp
index 276eb25..9897e08 100644
--- a/radiant/selection/shaderclipboard/ShaderClipboard.cpp
+++ b/radiant/selection/shaderclipboard/ShaderClipboard.cpp
@@ -20,10 +20,14 @@ ShaderClipboard::ShaderClipboard() :
GlobalUIManager().getStatusBarManager().addTextElement(
"ShaderClipBoard",
"icon_texture.png",
- IStatusBarManager::POS_SHADERCLIPBOARD
+ IStatusBarManager::POS_SHADERCLIPBOARD,
+ _("The name of the shader in the clipboard")
);
GlobalUndoSystem().addObserver(this);
+
+ GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &ShaderClipboard::onMapEvent));
}
void ShaderClipboard::clear() {
@@ -161,6 +165,14 @@ sigc::signal<void> ShaderClipboard::signal_sourceChanged() const
return _signalSourceChanged;
}
+void ShaderClipboard::onMapEvent(IMap::MapEvent ev)
+{
+ if (ev == IMap::MapUnloading)
+ {
+ clear();
+ }
+}
+
} // namespace selection
// global accessor function
diff --git a/radiant/selection/shaderclipboard/ShaderClipboard.h b/radiant/selection/shaderclipboard/ShaderClipboard.h
index 4167d1d..56e0543 100644
--- a/radiant/selection/shaderclipboard/ShaderClipboard.h
+++ b/radiant/selection/shaderclipboard/ShaderClipboard.h
@@ -1,10 +1,12 @@
#pragma once
#include "iundo.h"
+#include "imap.h"
#include "Texturable.h"
#include <sigc++/signal.h>
-namespace selection {
+namespace selection
+{
class ShaderClipboard :
public UndoSystem::Observer
@@ -56,6 +58,7 @@ public:
void postRedo();
private:
+ void onMapEvent(IMap::MapEvent ev);
/** greebo: Updates the shader information in the status bar.
*/
diff --git a/radiant/settings/GameManager.cpp b/radiant/settings/GameManager.cpp
index 027db16..896c58e 100644
--- a/radiant/settings/GameManager.cpp
+++ b/radiant/settings/GameManager.cpp
@@ -94,17 +94,17 @@ IGamePtr Manager::currentGame()
void Manager::constructPreferences()
{
- PreferencesPagePtr page = GetPreferenceSystem().getPage(_("Game"));
+ IPreferencePage& page = GetPreferenceSystem().getPage(_("Game"));
ComboBoxValueList gameList;
for (GameMap::iterator i = _games.begin(); i != _games.end(); ++i)
{
gameList.push_back(i->second->getKeyValue("name"));
}
- page->appendCombo(_("Select a Game:"), RKEY_GAME_TYPE, gameList, true);
- page->appendPathEntry(_("Engine Path"), RKEY_ENGINE_PATH, true);
- page->appendEntry(_("Mod (fs_game)"), RKEY_FS_GAME);
- page->appendEntry(_("Mod Base (fs_game_base, optional)"), RKEY_FS_GAME_BASE);
+ page.appendCombo(_("Select a Game:"), RKEY_GAME_TYPE, gameList, true);
+ page.appendPathEntry(_("Engine Path"), RKEY_ENGINE_PATH, true);
+ page.appendEntry(_("Mod (fs_game)"), RKEY_FS_GAME);
+ page.appendEntry(_("Mod Base (fs_game_base, optional)"), RKEY_FS_GAME_BASE);
}
void Manager::initialise(const std::string& appPath)
@@ -320,7 +320,7 @@ void Manager::initEnginePath()
while (!settingsValid())
{
// Engine path doesn't exist, ask the user
- ui::PrefDialog::ShowModal(_("Game"));
+ ui::PrefDialog::ShowDialog(_("Game"));
// After the dialog, the settings are located in the registry.
// Construct the paths with the settings found there
@@ -341,8 +341,8 @@ void Manager::initEnginePath()
updateEnginePath(true);
// Add the note to the preference page
- PreferencesPagePtr page = GetPreferenceSystem().getPage(_("Game"));
- page->appendLabel(_("<b>Note</b>: You will have to restart DarkRadiant\nfor the changes to take effect."));
+ IPreferencePage& page = GetPreferenceSystem().getPage(_("Game"));
+ page.appendLabel(_("<b>Note</b>: You will have to restart DarkRadiant\nfor the changes to take effect."));
}
void Manager::observeKey(const std::string& key)
diff --git a/radiant/settings/GameManager.h b/radiant/settings/GameManager.h
index 0de93e7..cdfc83a 100644
--- a/radiant/settings/GameManager.h
+++ b/radiant/settings/GameManager.h
@@ -63,10 +63,6 @@ private:
*/
bool settingsValid() const;
- /** greebo: Get the user engine path (is OS-specific)
- */
- std::string getUserEnginePath();
-
/**
* DerSaidin: Adds a path to the VFS search list, skipping any duplicates.
* Note that the order of search paths must be preserved.
@@ -96,25 +92,29 @@ public:
*/
const std::string& getEnginePath() const;
+ /** greebo: Get the user engine path (is OS-specific)
+ */
+ std::string getUserEnginePath() override;
+
/**
* greebo: Gets the mod path (e.g. ~/.doom3/gathers/).
* Returns the mod base path if the mod path itself is empty.
*/
- const std::string& getModPath() const;
+ const std::string& getModPath() const override;
/**
* greebo: Returns the mod base path (e.g. ~/.doom3/darkmod/),
* can be an empty string if fs_game_base is not set.
*/
- const std::string& getModBasePath() const;
+ const std::string& getModBasePath() const override;
/** greebo: Accessor method for the fs_game parameter
*/
- const std::string& getFSGame() const;
+ const std::string& getFSGame() const override;
/** greebo: Accessor method for the fs_game_base parameter
*/
- const std::string& getFSGameBase() const;
+ const std::string& getFSGameBase() const override;
/** greebo: Initialises the engine path from the settings in the registry.
* If nothing is found, the game file is queried.
@@ -123,7 +123,7 @@ public:
/** greebo: Returns the current Game (shared_ptr).
*/
- virtual IGamePtr currentGame();
+ virtual IGamePtr currentGame() override;
/** greebo: Loads the game files and the saved settings.
* If no saved game setting is found, the user
@@ -136,12 +136,12 @@ public:
void loadGameFiles(const std::string& appPath);
// Returns the sorted game path list
- virtual const PathList& getVFSSearchPaths() const;
+ virtual const PathList& getVFSSearchPaths() const override;
// RegisterableModule implementation
- virtual const std::string& getName() const;
- virtual const StringSet& getDependencies() const;
- virtual void initialiseModule(const ApplicationContext& ctx);
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
};
diff --git a/radiant/settings/LanguageManager.cpp b/radiant/settings/LanguageManager.cpp
index f5282b5..1e24485 100644
--- a/radiant/settings/LanguageManager.cpp
+++ b/radiant/settings/LanguageManager.cpp
@@ -101,10 +101,10 @@ void LanguageManager::initialiseModule(const ApplicationContext& ctx)
GlobalRegistry().setAttribute(RKEY_LANGUAGE, "volatile", "1"); // don't save this to user.xml
// Add Preferences
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Language"));
- page->appendCombo(_("Language"), RKEY_LANGUAGE, langs);
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Language"));
+ page.appendCombo(_("Language"), RKEY_LANGUAGE, langs);
- page->appendLabel(_("<b>Note:</b> You'll need to restart DarkRadiant\nafter changing the language setting."));
+ page.appendLabel(_("<b>Note:</b> You'll need to restart DarkRadiant\nafter changing the language setting."));
}
void LanguageManager::shutdownModule()
diff --git a/radiant/settings/PreferenceItemBase.h b/radiant/settings/PreferenceItemBase.h
new file mode 100644
index 0000000..51f9807
--- /dev/null
+++ b/radiant/settings/PreferenceItemBase.h
@@ -0,0 +1,44 @@
+#pragma once
+
+namespace settings
+{
+
+// Base class for all pereference items. All of them can carry
+// a title and a registry key
+class PreferenceItemBase
+{
+protected:
+ std::string _registryKey;
+
+ std::string _label;
+
+public:
+ PreferenceItemBase(const std::string& label) :
+ _label(label)
+ {}
+
+ PreferenceItemBase(const std::string& label, const std::string& registryKey) :
+ _registryKey(registryKey),
+ _label(label)
+ {}
+
+ virtual ~PreferenceItemBase() {}
+
+ virtual const std::string& getLabel() const
+ {
+ return _label;
+ }
+
+ virtual const std::string& getRegistryKey() const
+ {
+ return _registryKey;
+ }
+
+ virtual void setRegistryKey(const std::string& key)
+ {
+ _registryKey = key;
+ }
+};
+typedef std::shared_ptr<PreferenceItemBase> PreferenceItemBasePtr;
+
+} // namespace
diff --git a/radiant/settings/PreferenceItems.h b/radiant/settings/PreferenceItems.h
new file mode 100644
index 0000000..f630819
--- /dev/null
+++ b/radiant/settings/PreferenceItems.h
@@ -0,0 +1,170 @@
+#pragma once
+
+#include "ipreferencesystem.h"
+#include "PreferenceItemBase.h"
+
+/**
+ * greebo: This file contains a couple of classes describing
+ * the Preference Items visible in the Preference Dialog.
+ *
+ * Client code registers their configurable options with the
+ * GlobalPreferenceSystem during module initialisation, these
+ * classes here store this information for later retrieval
+ * (when the Preference Dialog is constructed, more specifically).
+ *
+ * All these are derived from a single base, as most of them
+ * want to save their stuff in the Registry.
+ */
+namespace settings
+{
+
+class PreferenceLabel :
+ public PreferenceItemBase
+{
+public:
+ PreferenceLabel(const std::string& label) :
+ PreferenceItemBase(label)
+ {}
+};
+
+class PreferenceEntry :
+ public PreferenceItemBase
+{
+public:
+ PreferenceEntry(const std::string& label, const std::string& registryKey) :
+ PreferenceItemBase(label, registryKey)
+ {}
+};
+
+class PreferenceCheckbox :
+ public PreferenceItemBase
+{
+public:
+ PreferenceCheckbox(const std::string& label, const std::string& registryKey) :
+ PreferenceItemBase(label, registryKey)
+ {}
+};
+
+class PreferenceCombobox :
+ public PreferenceItemBase
+{
+private:
+ ComboBoxValueList _values;
+ bool _storeValueNotIndex;
+
+public:
+ PreferenceCombobox(const std::string& label, const std::string& registryKey,
+ const ComboBoxValueList& values, bool storeValueNotIndex) :
+ PreferenceItemBase(label, registryKey),
+ _values(values),
+ _storeValueNotIndex(storeValueNotIndex)
+ {}
+
+ const ComboBoxValueList& getValues() const
+ {
+ return _values;
+ }
+
+ bool storeValueNotIndex() const
+ {
+ return _storeValueNotIndex;
+ }
+};
+
+class PreferencePathEntry :
+ public PreferenceItemBase
+{
+private:
+ bool _browseDirectories;
+
+public:
+ PreferencePathEntry(const std::string& label, const std::string& registryKey, bool browseDirectories) :
+ PreferenceItemBase(label, registryKey),
+ _browseDirectories(browseDirectories)
+ {}
+
+ bool browseDirectories() const
+ {
+ return _browseDirectories;
+ }
+};
+
+class PreferenceSpinner :
+ public PreferenceItemBase
+{
+private:
+ double _lower;
+ double _upper;
+ int _fraction;
+
+public:
+ PreferenceSpinner(const std::string& label, const std::string& registryKey, double lower, double upper, int fraction) :
+ PreferenceItemBase(label, registryKey),
+ _lower(lower),
+ _upper(upper),
+ _fraction(fraction)
+ {}
+
+ double getLower()
+ {
+ return _lower;
+ }
+
+ double getUpper()
+ {
+ return _upper;
+ }
+
+ int getFraction()
+ {
+ return _fraction;
+ }
+};
+
+class PreferenceSlider :
+ public PreferenceItemBase
+{
+private:
+ double _lower;
+ double _upper;
+ double _stepIncrement;
+ double _pageIncrement;
+ int _factor;
+
+public:
+ PreferenceSlider(const std::string& label, const std::string& registryKey, double lower, double upper, double stepIncrement, double pageIncrement) :
+ PreferenceItemBase(label, registryKey),
+ _lower(lower),
+ _upper(upper),
+ _stepIncrement(stepIncrement),
+ _pageIncrement(pageIncrement),
+ _factor(1)
+ {}
+
+ double getLower()
+ {
+ return _lower;
+ }
+
+ double getUpper()
+ {
+ return _upper;
+ }
+
+ double getStepIncrement()
+ {
+ return _stepIncrement;
+ }
+
+ double getPageIncrement()
+ {
+ return _pageIncrement;
+ }
+
+ int getFactor()
+ {
+ return _factor;
+ }
+};
+
+} // namespace
diff --git a/radiant/settings/PreferencePage.cpp b/radiant/settings/PreferencePage.cpp
new file mode 100644
index 0000000..ac0ca4d
--- /dev/null
+++ b/radiant/settings/PreferencePage.cpp
@@ -0,0 +1,159 @@
+#include "PreferencePage.h"
+
+#include <stdexcept>
+#include "i18n.h"
+#include "itextstream.h"
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/format.hpp>
+
+#include "PreferenceItems.h"
+
+namespace settings
+{
+
+PreferencePage::PreferencePage(const std::string& name, const PreferencePagePtr& parentPage) :
+ _name(name)
+{
+ _title = (boost::format(_("%s Settings")) % _name).str();
+
+ // Construct the _path member value
+ if (parentPage && !parentPage->getPath().empty())
+ {
+ _path = parentPage->getPath() + "/" + _name;
+ }
+ else
+ {
+ _path = _name;
+ }
+}
+
+const std::string& PreferencePage::getTitle() const
+{
+ return _title;
+}
+
+void PreferencePage::setTitle(const std::string& title)
+{
+ _title = title;
+}
+
+const std::string& PreferencePage::getPath() const
+{
+ return _path;
+}
+
+const std::string& PreferencePage::getName() const
+{
+ return _name;
+}
+
+PreferencePage& PreferencePage::createOrFindPage(const std::string& path)
+{
+ // Split the path into parts
+ std::list<std::string> parts;
+ boost::algorithm::split(parts, path, boost::algorithm::is_any_of("/"));
+
+ if (parts.empty())
+ {
+ rConsole() << "Cannot resolve empty preference path: " << path << std::endl;
+ throw std::logic_error("Cannot resolve empty preference path.");
+ }
+
+ PreferencePagePtr child;
+
+ // Try to lookup the page in the child list
+ for (const PreferencePagePtr& candidate : _children)
+ {
+ if (candidate->getName() == parts.front())
+ {
+ child = candidate;
+ break;
+ }
+ }
+
+ if (!child)
+ {
+ // No child found, create a new page and add it to the list
+ child = std::make_shared<PreferencePage>(parts.front(), shared_from_this());
+ _children.push_back(child);
+ }
+
+ // We now have a child with this name, do we have a leaf?
+ if (parts.size() > 1)
+ {
+ // We have still more parts, split off the first part
+ parts.pop_front();
+ std::string subPath = boost::algorithm::join(parts, "/");
+
+ // Pass the call to the child
+ return child->createOrFindPage(subPath);
+ }
+ else
+ {
+ // We have found a leaf, return the child page
+ return *child;
+ }
+}
+
+void PreferencePage::foreachChildPage(const std::function<void(PreferencePage&)>& functor)
+{
+ for (const PreferencePagePtr& child : _children)
+ {
+ // Visit this instance
+ functor(*child);
+
+ // Pass the visitor recursively
+ child->foreachChildPage(functor);
+ }
+}
+
+void PreferencePage::foreachItem(const std::function<void(const PreferenceItemBasePtr&)>& functor) const
+{
+ for (const PreferenceItemBasePtr& item : _items)
+ {
+ functor(item);
+ }
+}
+
+void PreferencePage::appendCheckBox(const std::string& label, const std::string& registryKey)
+{
+ _items.push_back(std::make_shared<PreferenceCheckbox>(label, registryKey));
+}
+
+void PreferencePage::appendSlider(const std::string& name, const std::string& registryKey,
+ double lower, double upper, double stepIncrement, double pageIncrement)
+{
+ _items.push_back(std::make_shared<PreferenceSlider>(name, registryKey,
+ lower, upper, stepIncrement, pageIncrement));
+}
+
+void PreferencePage::appendCombo(const std::string& name, const std::string& registryKey,
+ const ComboBoxValueList& valueList, bool storeValueNotIndex)
+{
+ _items.push_back(std::make_shared<PreferenceCombobox>(name, registryKey, valueList, storeValueNotIndex));
+}
+
+void PreferencePage::appendEntry(const std::string& name, const std::string& registryKey)
+{
+ _items.push_back(std::make_shared<PreferenceEntry>(name, registryKey));
+}
+
+void PreferencePage::appendLabel(const std::string& caption)
+{
+ _items.push_back(std::make_shared<PreferenceLabel>(caption));
+}
+
+void PreferencePage::appendPathEntry(const std::string& name, const std::string& registryKey, bool browseDirectories)
+{
+ _items.push_back(std::make_shared<PreferencePathEntry>(name, registryKey, browseDirectories));
+}
+
+void PreferencePage::appendSpinner(const std::string& name, const std::string& registryKey,
+ double lower, double upper, int fraction)
+{
+ _items.push_back(std::make_shared<PreferenceSpinner>(name, registryKey, lower, upper, fraction));
+}
+
+} // namespace
diff --git a/radiant/settings/PreferencePage.h b/radiant/settings/PreferencePage.h
new file mode 100644
index 0000000..81041eb
--- /dev/null
+++ b/radiant/settings/PreferencePage.h
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "ipreferencesystem.h"
+#include <vector>
+#include <memory>
+
+#include "PreferenceItemBase.h"
+
+namespace settings
+{
+
+class PreferencePage;
+typedef std::shared_ptr<PreferencePage> PreferencePagePtr;
+
+class PreferencePage :
+ public IPreferencePage,
+ public std::enable_shared_from_this<PreferencePage>
+{
+private:
+ // The name (caption) of this page
+ std::string _name;
+
+ // The title which is by default "{_name} Settings" but can be overridden
+ std::string _title;
+
+ // The full path of this object
+ std::string _path;
+
+ // The list of child pages
+ std::vector<PreferencePagePtr> _children;
+
+ // The registered items
+ std::vector<PreferenceItemBasePtr> _items;
+
+public:
+ /**
+ * Construct this passing the name and the optional parent page.
+ */
+ PreferencePage(const std::string& name,
+ const PreferencePagePtr& parentPage = PreferencePagePtr());
+
+ // Returns the title as displayed on top of the page's area
+ const std::string& getTitle() const;
+
+ /**
+ * greebo: Sets the title caption that is displayed on the right.
+ * Overrides the default title that is generated
+ * on construction (the one with the " Settings" postfix).
+ */
+ void setTitle(const std::string& title) override;
+
+ // greebo: Returns the full path to this page
+ const std::string& getPath() const;
+
+ // greebo: Returns the name (caption) of this Page (e.g. "Settings")
+ const std::string& getName() const;
+
+ /**
+ * greebo: Performs a recursive lookup of the given path
+ * and creates any items that do not exist.
+ * @returns: the shared_ptr to the PrefPage.
+ * @throws: a std::logic_error if the given path is empty
+ */
+ PreferencePage& createOrFindPage(const std::string& path);
+
+ // Recursively visit all children of this page
+ void foreachChildPage(const std::function<void(PreferencePage&)>& functor);
+
+ // Hit the functor with each item on this page
+ void foreachItem(const std::function<void(const PreferenceItemBasePtr&)>& functor) const;
+
+ // IPreferencePage implementation
+ void appendCheckBox(const std::string& label, const std::string& registryKey) override;
+
+ void appendSlider(const std::string& name, const std::string& registryKey,
+ double lower, double upper, double stepIncrement, double pageIncrement) override;
+
+ void appendCombo(const std::string& name,
+ const std::string& registryKey,
+ const ComboBoxValueList& valueList,
+ bool storeValueNotIndex = false) override;
+
+ void appendEntry(const std::string& name, const std::string& registryKey) override;
+
+ void appendSpinner(const std::string& name, const std::string& registryKey,
+ double lower, double upper, int fraction) override;
+
+ void appendPathEntry(const std::string& name, const std::string& registryKey,
+ bool browseDirectories) override;
+
+ void appendLabel(const std::string& caption) override;
+};
+
+}
\ No newline at end of file
diff --git a/radiant/settings/PreferenceSystem.cpp b/radiant/settings/PreferenceSystem.cpp
index 60f4649..832d5cf 100644
--- a/radiant/settings/PreferenceSystem.cpp
+++ b/radiant/settings/PreferenceSystem.cpp
@@ -2,55 +2,59 @@
#include "ipreferencesystem.h"
#include "itextstream.h"
-#include "imodule.h"
-#include "iregistry.h"
-
-#include <time.h>
-#include <iostream>
-
-#include "os/file.h"
-#include "string/string.h"
#include "modulesystem/StaticModule.h"
-#include "modulesystem/ApplicationContextImpl.h"
#include "ui/prefdialog/PrefDialog.h"
-#include <boost/algorithm/string/replace.hpp>
+namespace settings
+{
-class PreferenceSystem :
- public IPreferenceSystem
+IPreferencePage& PreferenceSystem::getPage(const std::string& path)
{
-public:
- // Looks up a page for the given path and returns it to the client
- PreferencesPagePtr getPage(const std::string& path) {
- return ui::PrefDialog::Instance().createOrFindPage(path);
- }
+ ensureRootPage();
- // RegisterableModule implementation
- virtual const std::string& getName() const {
- static std::string _name(MODULE_PREFERENCESYSTEM);
- return _name;
- }
+ return _rootPage->createOrFindPage(path);
+}
- virtual const StringSet& getDependencies() const {
- static StringSet _dependencies;
+void PreferenceSystem::foreachPage(const std::function<void(PreferencePage&)>& functor)
+{
+ ensureRootPage();
- if (_dependencies.empty()) {
- _dependencies.insert(MODULE_XMLREGISTRY);
- _dependencies.insert(MODULE_RADIANT);
- }
+ _rootPage->foreachChildPage(functor);
+}
- return _dependencies;
+void PreferenceSystem::ensureRootPage()
+{
+ if (!_rootPage)
+ {
+ _rootPage = std::make_shared<PreferencePage>("");
}
+}
- virtual void initialiseModule(const ApplicationContext& ctx) {
- rMessage() << "PreferenceSystem::initialiseModule called\n";
- }
-};
+// RegisterableModule implementation
+const std::string& PreferenceSystem::getName() const
+{
+ static std::string _name(MODULE_PREFERENCESYSTEM);
+ return _name;
+}
+
+const StringSet& PreferenceSystem::getDependencies() const
+{
+ static StringSet _dependencies;
+ return _dependencies;
+}
+
+void PreferenceSystem::initialiseModule(const ApplicationContext& ctx)
+{
+ rMessage() << "PreferenceSystem::initialiseModule called" << std::endl;
+}
// Define the static PreferenceSystem module
module::StaticModule<PreferenceSystem> preferenceSystemModule;
-IPreferenceSystem& GetPreferenceSystem() {
- return *preferenceSystemModule.getModule();
+}
+
+settings::PreferenceSystem& GetPreferenceSystem()
+{
+ return *settings::preferenceSystemModule.getModule();
}
diff --git a/radiant/settings/PreferenceSystem.h b/radiant/settings/PreferenceSystem.h
index a3db104..9d21563 100644
--- a/radiant/settings/PreferenceSystem.h
+++ b/radiant/settings/PreferenceSystem.h
@@ -1,14 +1,38 @@
-#ifndef PREFERENCESYSTEM_H_
-#define PREFERENCESYSTEM_H_
+#pragma once
-#include <string>
-class IPreferenceSystem;
+#include "ipreferencesystem.h"
+#include "PreferencePage.h"
-/** greebo: Direct accessor method for the preferencesystem for situations
- * where the actual PreferenceSystemModule is not loaded yet.
- *
- * Everything else should use the GlobalPreferenceSystem() access method.
- */
-IPreferenceSystem& GetPreferenceSystem();
+namespace settings
+{
+
+class PreferenceSystem :
+ public IPreferenceSystem
+{
+private:
+ PreferencePagePtr _rootPage;
+
+public:
+ // Looks up a page for the given path and returns it to the client
+ IPreferencePage& getPage(const std::string& path) override;
+
+ // Internal method to walk over the registered pages
+ void foreachPage(const std::function<void(PreferencePage&)>& functor);
-#endif /*PREFERENCESYSTEM_H_*/
+ // RegisterableModule implementation
+ virtual const std::string& getName() const override;
+ virtual const StringSet& getDependencies() const override;
+ virtual void initialiseModule(const ApplicationContext& ctx) override;
+
+private:
+ void ensureRootPage();
+};
+
+} // namespace
+
+/**
+ * greebo: Direct accessor method for the preferencesystem for situations
+ * where the actual PreferenceSystemModule is not loaded yet.
+ * Everything else should use the GlobalPreferenceSystem() access method.
+ */
+settings::PreferenceSystem& GetPreferenceSystem();
diff --git a/radiant/textool/item/PatchItem.cpp b/radiant/textool/item/PatchItem.cpp
index 95b826a..289e7c9 100644
--- a/radiant/textool/item/PatchItem.cpp
+++ b/radiant/textool/item/PatchItem.cpp
@@ -32,11 +32,11 @@ void PatchItem::render() {
const RenderIndex* strip_indices = &tess.indices.front();
- for (std::size_t i = 0; i < tess.m_numStrips; i++, strip_indices += tess.m_lenStrips)
+ for (std::size_t i = 0; i < tess.numStrips; i++, strip_indices += tess.lenStrips)
{
glBegin(GL_QUAD_STRIP);
- for (std::size_t offset = 0; offset < tess.m_lenStrips; offset++)
+ for (std::size_t offset = 0; offset < tess.lenStrips; offset++)
{
// Retrieve the mesh vertex from the line strip
ArbitraryMeshVertex& meshVertex = tess.vertices[*(strip_indices + offset)];
diff --git a/radiant/ui/aas/AasControl.cpp b/radiant/ui/aas/AasControl.cpp
new file mode 100644
index 0000000..109b92e
--- /dev/null
+++ b/radiant/ui/aas/AasControl.cpp
@@ -0,0 +1,123 @@
+#include "AasControl.h"
+
+#include "i18n.h"
+#include "iarchive.h"
+#include "imainframe.h"
+#include "iuimanager.h"
+#include "ifilesystem.h"
+
+#include <wx/event.h>
+#include <wx/button.h>
+#include <wx/bmpbuttn.h>
+#include <wx/tglbtn.h>
+#include <wx/sizer.h>
+#include <wx/artprov.h>
+#include <memory>
+
+#include "map/RenderableAasFile.h"
+
+namespace ui
+{
+
+AasControl::AasControl(wxWindow* parent, const map::AasFileInfo& info) :
+ _toggle(nullptr),
+ _refreshButton(nullptr),
+ _buttonHBox(nullptr),
+ _updateActive(nullptr),
+ _info(info)
+{
+ // Create the main toggle
+ _toggle = new wxToggleButton(parent, wxID_ANY, info.type.fileExtension);
+ _toggle->Connect(wxEVT_TOGGLEBUTTON, wxCommandEventHandler(AasControl::onToggle), NULL, this);
+
+ _refreshButton = new wxBitmapButton(parent, wxID_ANY,
+ wxArtProvider::GetBitmap(GlobalUIManager().ArtIdPrefix() + "refresh.png"));
+ _refreshButton->Connect(wxEVT_BUTTON, wxCommandEventHandler(AasControl::onRefresh), NULL, this);
+ _refreshButton->SetToolTip(_("Reload AAS File"));
+
+ _buttonHBox = new wxBoxSizer(wxHORIZONTAL);
+ _buttonHBox->Add(_refreshButton, 0, wxEXPAND);
+
+ // Refresh the Control
+ update();
+}
+
+AasControl::~AasControl()
+{
+ // Detach before destruction
+ if (_toggle->GetValue())
+ {
+ GlobalRenderSystem().detachRenderable(_renderable);
+ }
+}
+
+wxSizer* AasControl::getButtons()
+{
+ return _buttonHBox;
+}
+
+wxToggleButton* AasControl::getToggle()
+{
+ return _toggle;
+}
+
+void AasControl::update()
+{
+
+}
+
+void AasControl::ensureAasFileLoaded()
+{
+ if (_aasFile) return;
+
+ ArchiveTextFilePtr file = GlobalFileSystem().openTextFileInAbsolutePath(_info.absolutePath);
+
+ if (file)
+ {
+ std::istream stream(&file->getInputStream());
+ map::IAasFileLoaderPtr loader = GlobalAasFileManager().getLoaderForStream(stream);
+
+ if (loader && loader->canLoad(stream))
+ {
+ stream.seekg(0, std::ios_base::beg);
+
+ _aasFile = loader->loadFromStream(stream);
+
+ // Construct a renderable to attach to the rendersystem
+ _renderable.setAasFile(_aasFile);
+ }
+ }
+}
+
+void AasControl::onToggle(wxCommandEvent& ev)
+{
+ if (_toggle->GetValue())
+ {
+ ensureAasFileLoaded();
+ GlobalRenderSystem().attachRenderable(_renderable);
+ }
+ else
+ {
+ // Disable rendering
+ GlobalRenderSystem().detachRenderable(_renderable);
+ }
+
+ GlobalMainFrame().updateAllWindows();
+}
+
+void AasControl::onRefresh(wxCommandEvent& ev)
+{
+ // Detach renderable
+ _aasFile.reset();
+
+ if (_toggle->GetValue())
+ {
+ GlobalRenderSystem().detachRenderable(_renderable);
+
+ ensureAasFileLoaded();
+
+ GlobalRenderSystem().attachRenderable(_renderable);
+ }
+}
+
+} // namespace ui
diff --git a/radiant/ui/aas/AasControl.h b/radiant/ui/aas/AasControl.h
new file mode 100644
index 0000000..61e4145
--- /dev/null
+++ b/radiant/ui/aas/AasControl.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <wx/event.h>
+#include <memory>
+#include "iaasfile.h"
+#include "map/RenderableAasFile.h"
+
+class wxWindow;
+class wxButton;
+class wxToggleButton;
+class wxSizer;
+
+namespace ui
+{
+
+/**
+ * greebo: An AasControl contains a set of widgets needed
+ * to control an associated AAS file.
+ *
+ * Multiple of these Controls can be packed as children into the
+ * owning AasControlDialog.
+ */
+class AasControl :
+ public wxEvtHandler
+{
+private:
+ wxToggleButton* _toggle;
+ wxButton* _refreshButton;
+ wxSizer* _buttonHBox;
+
+ // Locks down the callbacks during widget update
+ bool _updateActive;
+
+ // The AAS file this control is referring to
+ map::AasFileInfo _info;
+
+ // The AAS file reference (can be empty)
+ map::IAasFilePtr _aasFile;
+
+ // The renderable that is attached to the rendersystem when active
+ map::RenderableAasFile _renderable;
+
+public:
+ AasControl(wxWindow* parent, const map::AasFileInfo& info);
+
+ virtual ~AasControl();
+
+ // Returns the widgets for packing this object into a container/table
+ wxSizer* getButtons();
+ wxToggleButton* getToggle();
+
+ // Updates the state of all widgets
+ void update();
+
+private:
+ void ensureAasFileLoaded();
+
+ void onToggle(wxCommandEvent& ev);
+ void onRefresh(wxCommandEvent& ev);
+};
+typedef std::shared_ptr<AasControl> AasControlPtr;
+
+} // namespace ui
diff --git a/radiant/ui/aas/AasControlDialog.cpp b/radiant/ui/aas/AasControlDialog.cpp
new file mode 100644
index 0000000..25860dc
--- /dev/null
+++ b/radiant/ui/aas/AasControlDialog.cpp
@@ -0,0 +1,237 @@
+#include "AasControlDialog.h"
+
+#include "i18n.h"
+#include "iaasfile.h"
+#include "iradiant.h"
+#include "imainframe.h"
+#include "itextstream.h"
+#include "ieventmanager.h"
+
+#include <wx/button.h>
+#include <wx/tglbtn.h>
+#include <wx/sizer.h>
+#include <wx/panel.h>
+#include <wx/scrolwin.h>
+
+#include "registry/Widgets.h"
+#include "map/Map.h"
+#include "map/RenderableAasFile.h"
+
+namespace ui
+{
+
+namespace
+{
+ const std::string RKEY_ROOT = "user/ui/aas/controlDialog/";
+ const std::string RKEY_WINDOW_STATE = RKEY_ROOT + "window";
+}
+
+AasControlDialog::AasControlDialog() :
+ TransientWindow(_("AAS Viewer"), GlobalMainFrame().getWxTopLevelWindow(), true),
+ _dialogPanel(nullptr),
+ _controlContainer(nullptr)
+{
+ populateWindow();
+
+ InitialiseWindowPosition(135, 100, RKEY_WINDOW_STATE);
+ SetMinClientSize(wxSize(135, 100));
+
+ _mapEventSlot = GlobalMapModule().signal_mapEvent().connect(
+ sigc::mem_fun(*this, &AasControlDialog::onMapEvent));
+}
+
+void AasControlDialog::onMapEvent(IMap::MapEvent ev)
+{
+ switch (ev)
+ {
+ case IMap::MapEvent::MapLoaded:
+ refresh();
+ break;
+ case IMap::MapEvent::MapUnloading:
+ clearControls();
+ break;
+ default:
+ break;
+ };
+}
+
+void AasControlDialog::populateWindow()
+{
+ wxScrolledWindow* dialogPanel = new wxScrolledWindow(this, wxID_ANY);
+ dialogPanel->SetScrollRate(0, 15);
+
+ _dialogPanel = dialogPanel;
+
+ _dialogPanel->SetSizer(new wxBoxSizer(wxVERTICAL));
+
+ _controlContainer = new wxFlexGridSizer(1, 2, 3, 3);
+ _controlContainer->AddGrowableCol(0);
+
+ _dialogPanel->GetSizer()->Add(_controlContainer, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 12);
+
+ createButtons();
+
+ _dialogPanel->FitInside(); // ask the sizer about the needed size
+}
+
+void AasControlDialog::createButtons()
+{
+ // Rescan button
+ _rescanButton = new wxButton(_dialogPanel, wxID_ANY, _("Search for AAS Files"));
+ _rescanButton->Bind(wxEVT_BUTTON, [this](wxCommandEvent& ev) { refresh(); });
+
+ // Bind the toggle button to the registry key
+ wxToggleButton* showNumbersButton = new wxToggleButton(_dialogPanel, wxID_ANY, _("Show Area Numbers"));
+ registry::bindWidget(showNumbersButton, map::RKEY_SHOW_AAS_AREA_NUMBERS);
+
+ wxToggleButton* hideDistantAreasButton = new wxToggleButton(_dialogPanel, wxID_ANY, _("Hide distant Areas"));
+ registry::bindWidget(hideDistantAreasButton, map::RKEY_HIDE_DISTANT_AAS_AREAS);
+
+ _dialogPanel->GetSizer()->Add(showNumbersButton, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 12);
+ _dialogPanel->GetSizer()->Add(hideDistantAreasButton, 0, wxEXPAND | wxLEFT | wxRIGHT, 12);
+ _dialogPanel->GetSizer()->Add(_rescanButton, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 12);
+}
+
+void AasControlDialog::clearControls()
+{
+ // Remove all previously allocated controls
+ _aasControls.clear();
+
+ // Delete all wxWidgets objects
+ _controlContainer->Clear(true);
+}
+
+void AasControlDialog::refresh()
+{
+ clearControls();
+
+ std::map<std::string, AasControlPtr> sortedControls;
+
+ // Find all available AAS files for the current map
+
+ std::list<map::AasFileInfo> aasFiles = GlobalAasFileManager().getAasFilesForMap(GlobalMap().getMapName());
+
+ for (map::AasFileInfo& info : aasFiles)
+ {
+ // Create a new control for each AAS type
+ // Store the object in a sorted container
+ sortedControls[info.type.fileExtension] = std::make_shared<AasControl>(_dialogPanel, info);
+ }
+
+ // Assign all controls to the target vector, alphabetically sorted
+ for (const auto& pair : sortedControls)
+ {
+ _aasControls.push_back(pair.second);
+ }
+
+ _controlContainer->SetRows(static_cast<int>(_aasControls.size()));
+
+ for (AasControls::iterator i = _aasControls.begin(); i != _aasControls.end(); ++i)
+ {
+ _controlContainer->Add((*i)->getToggle(), 1, wxEXPAND);
+ _controlContainer->Add((*i)->getButtons(), 0, wxEXPAND);
+
+ if (i == _aasControls.begin())
+ {
+ // Prevent setting the focus on the buttons at the bottom which lets the scrollbar
+ // of the window jump around, set the focus on the first button.
+ (*i)->getToggle()->SetFocus();
+ }
+ }
+
+ _controlContainer->Layout();
+ _dialogPanel->FitInside(); // ask the sizer about the needed size
+
+ update();
+}
+
+void AasControlDialog::update()
+{
+ // Broadcast the update() call
+ for (const AasControlPtr& control : _aasControls)
+ {
+ control->update();
+ }
+}
+
+// TransientWindow callbacks
+void AasControlDialog::_preShow()
+{
+ TransientWindow::_preShow();
+
+ // Re-populate the dialog
+ refresh();
+}
+
+void AasControlDialog::OnRadiantStartup()
+{
+ // Lookup the stored window information in the registry
+ if (GlobalRegistry().getAttribute(RKEY_WINDOW_STATE, "visible") == "1")
+ {
+ // Show dialog
+ Instance().Show();
+ }
+}
+
+void AasControlDialog::onRadiantShutdown()
+{
+ rMessage() << "AasControlDialog shutting down." << std::endl;
+
+ _mapEventSlot.disconnect();
+
+ // Write the visibility status to the registry
+ GlobalRegistry().setAttribute(RKEY_WINDOW_STATE, "visible", IsShownOnScreen() ? "1" : "0");
+
+ // Hide the window and save its state
+ if (IsShownOnScreen())
+ {
+ Hide();
+ }
+
+ // Destroy the window (after it has been disconnected from the Eventmanager)
+ SendDestroyEvent();
+
+ // Final step: clear the instance pointer
+ InstancePtr().reset();
+}
+
+AasControlDialogPtr& AasControlDialog::InstancePtr()
+{
+ static AasControlDialogPtr _instancePtr;
+ return _instancePtr;
+}
+
+AasControlDialog& AasControlDialog::Instance()
+{
+ AasControlDialogPtr& instancePtr = InstancePtr();
+
+ if (instancePtr == NULL)
+ {
+ // Not yet instantiated, do it now
+ instancePtr.reset(new AasControlDialog);
+
+ // Register this instance with GlobalRadiant() at once
+ GlobalRadiant().signal_radiantShutdown().connect(
+ sigc::mem_fun(*instancePtr, &AasControlDialog::onRadiantShutdown)
+ );
+ }
+
+ return *instancePtr;
+}
+
+void AasControlDialog::Init()
+{
+ GlobalCommandSystem().addCommand("ToggleAasControlDialog", AasControlDialog::Toggle);
+ GlobalEventManager().addCommand("ToggleAasControlDialog", "ToggleAasControlDialog");
+
+ GlobalRadiant().signal_radiantStarted().connect(
+ sigc::ptr_fun(&AasControlDialog::OnRadiantStartup)
+ );
+}
+
+void AasControlDialog::Toggle(const cmd::ArgumentList& args)
+{
+ Instance().ToggleVisibility();
+}
+
+}
diff --git a/radiant/ui/aas/AasControlDialog.h b/radiant/ui/aas/AasControlDialog.h
new file mode 100644
index 0000000..c30f872
--- /dev/null
+++ b/radiant/ui/aas/AasControlDialog.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "wxutil/window/TransientWindow.h"
+#include "AasControl.h"
+#include "imap.h"
+#include "icommandsystem.h"
+#include <sigc++/connection.h>
+
+class wxFlexGridSizer;
+class wxButton;
+class wxPanel;
+
+namespace ui
+{
+
+class AasControlDialog;
+typedef std::shared_ptr<AasControlDialog> AasControlDialogPtr;
+
+class AasControlDialog :
+ public wxutil::TransientWindow
+{
+private:
+ typedef std::vector<AasControlPtr> AasControls;
+ AasControls _aasControls;
+
+ wxPanel* _dialogPanel;
+
+ wxFlexGridSizer* _controlContainer;
+ wxButton* _rescanButton;
+
+ sigc::connection _mapEventSlot;
+
+public:
+ AasControlDialog();
+
+ // Re-populates the window
+ void refresh();
+
+ // Updates the state of all controls
+ void update();
+
+ // Command target (registered in the event manager)
+ static void Toggle(const cmd::ArgumentList& args);
+
+ // Called during AAS module initialisation
+ static void Init();
+ static void OnRadiantStartup();
+
+ static AasControlDialog& Instance();
+
+private:
+ static AasControlDialogPtr& InstancePtr();
+
+ // TransientWindow events
+ void _preShow();
+
+ void populateWindow();
+ void createButtons();
+ void onRadiantShutdown();
+ void clearControls();
+
+ void onMapEvent(IMap::MapEvent ev);
+};
+
+}
diff --git a/radiant/ui/einspector/AnglePropertyEditor.h b/radiant/ui/einspector/AnglePropertyEditor.h
index acbb50b..fd87f5f 100644
--- a/radiant/ui/einspector/AnglePropertyEditor.h
+++ b/radiant/ui/einspector/AnglePropertyEditor.h
@@ -47,7 +47,7 @@ public:
/* PropertyEditor implementation */
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& key,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new AnglePropertyEditor(parent, entity, key));
}
diff --git a/radiant/ui/einspector/BooleanPropertyEditor.cpp b/radiant/ui/einspector/BooleanPropertyEditor.cpp
index e37a9dc..4dee2da 100644
--- a/radiant/ui/einspector/BooleanPropertyEditor.cpp
+++ b/radiant/ui/einspector/BooleanPropertyEditor.cpp
@@ -31,13 +31,19 @@ BooleanPropertyEditor::BooleanPropertyEditor(wxWindow* parent, Entity* entity,
// Create the checkbox with correct initial state, and connect up the
// toggle callback
_checkBox = new wxCheckBox(mainVBox, wxID_ANY, name);
- _checkBox->SetValue(_entity->getKeyValue(_key) == "1");
+
+ updateFromEntity();
_checkBox->Connect(wxEVT_CHECKBOX, wxCommandEventHandler(BooleanPropertyEditor::_onToggle), NULL, this);
mainVBox->GetSizer()->Add(_checkBox, 0, wxALIGN_CENTER_VERTICAL);
}
+void BooleanPropertyEditor::updateFromEntity()
+{
+ _checkBox->SetValue(_entity->getKeyValue(_key) == "1");
+}
+
void BooleanPropertyEditor::_onToggle(wxCommandEvent& ev)
{
// Set the key based on the checkbutton state
diff --git a/radiant/ui/einspector/BooleanPropertyEditor.h b/radiant/ui/einspector/BooleanPropertyEditor.h
index 8bd1b10..406b344 100644
--- a/radiant/ui/einspector/BooleanPropertyEditor.h
+++ b/radiant/ui/einspector/BooleanPropertyEditor.h
@@ -36,10 +36,12 @@ public:
// PropertyEditorFactory
BooleanPropertyEditor();
+ void updateFromEntity() override;
+
// Create a new BooleanPropertyEditor
virtual IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new BooleanPropertyEditor(parent, entity, name));
}
diff --git a/radiant/ui/einspector/ClassnamePropertyEditor.cpp b/radiant/ui/einspector/ClassnamePropertyEditor.cpp
index dd4c3df..4a6567c 100644
--- a/radiant/ui/einspector/ClassnamePropertyEditor.cpp
+++ b/radiant/ui/einspector/ClassnamePropertyEditor.cpp
@@ -8,6 +8,7 @@
#include <wx/panel.h>
#include <wx/button.h>
#include <wx/sizer.h>
+#include "wxutil/dialog/MessageBox.h"
#include "selection/algorithm/Entity.h"
#include "ui/entitychooser/EntityClassChooser.h"
@@ -38,8 +39,15 @@ void ClassnamePropertyEditor::onBrowseButtonClick()
{
UndoableCommand cmd("changeEntityClass");
- // Apply the classname change to the entity, this requires some algorithm
- selection::algorithm::setEntityClassname(selection);
+ try
+ {
+ // Apply the classname change to the entity, this requires some algorithm
+ selection::algorithm::setEntityClassname(selection);
+ }
+ catch (std::runtime_error& ex)
+ {
+ wxutil::Messagebox::ShowError(ex.what());
+ }
}
}
diff --git a/radiant/ui/einspector/ClassnamePropertyEditor.h b/radiant/ui/einspector/ClassnamePropertyEditor.h
index d0cb635..467d5d3 100644
--- a/radiant/ui/einspector/ClassnamePropertyEditor.h
+++ b/radiant/ui/einspector/ClassnamePropertyEditor.h
@@ -37,7 +37,7 @@ public:
// Clone method for virtual construction
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(
new ClassnamePropertyEditor(parent, entity, name, options)
diff --git a/radiant/ui/einspector/ColourPropertyEditor.cpp b/radiant/ui/einspector/ColourPropertyEditor.cpp
index 56ae6a0..954fb76 100644
--- a/radiant/ui/einspector/ColourPropertyEditor.cpp
+++ b/radiant/ui/einspector/ColourPropertyEditor.cpp
@@ -40,8 +40,13 @@ ColourPropertyEditor::ColourPropertyEditor(wxWindow* parent, Entity* entity,
mainVBox->GetSizer()->Add(_colorButton, 1, wxEXPAND | wxALL, 15);
+ updateFromEntity();
+}
+
+void ColourPropertyEditor::updateFromEntity()
+{
// Set colour button's colour
- setColourButton(_entity->getKeyValue(name));
+ setColourButton(_entity->getKeyValue(_key));
}
// Set displayed colour from the keyvalue
diff --git a/radiant/ui/einspector/ColourPropertyEditor.h b/radiant/ui/einspector/ColourPropertyEditor.h
index 45bb2b5..eb283e1 100644
--- a/radiant/ui/einspector/ColourPropertyEditor.h
+++ b/radiant/ui/einspector/ColourPropertyEditor.h
@@ -44,10 +44,12 @@ public:
/// Blank constructor for the PropertyEditorFactory
ColourPropertyEditor();
+ void updateFromEntity() override;
+
/// Create a new ColourPropertyEditor
virtual IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new ColourPropertyEditor(parent, entity, name));
}
diff --git a/radiant/ui/einspector/EntityInspector.cpp b/radiant/ui/einspector/EntityInspector.cpp
index e3bffc8..e3ac3f5 100644
--- a/radiant/ui/einspector/EntityInspector.cpp
+++ b/radiant/ui/einspector/EntityInspector.cpp
@@ -232,6 +232,20 @@ void EntityInspector::onKeyChange(const std::string& key,
row[_columns.name] = wxVariant(wxDataViewIconText(key, icon));
row[_columns.value] = value;
+ if (parms.type == "bool")
+ {
+ // Render a checkbox for boolean values (store an actual bool)
+ row[_columns.booleanValue] = value == "1";
+
+ // Column is enabled by default after assignment
+ }
+ else
+ {
+ // Store false to render the checkbox as unchecked
+ row[_columns.booleanValue] = false;
+ row[_columns.booleanValue].setEnabled(false);
+ }
+
// Text colour
row[_columns.name] = black;
row[_columns.value] = black;
@@ -261,6 +275,12 @@ void EntityInspector::onKeyChange(const std::string& key,
{
_valEntry->SetValue(value);
}
+
+ // Also update the property editor if the changed key is highlighted
+ if (_currentPropertyEditor && key == selectedKey)
+ {
+ _currentPropertyEditor->updateFromEntity();
+ }
}
void EntityInspector::onKeyErase(const std::string& key,
@@ -290,7 +310,8 @@ void EntityInspector::createContextMenu()
_contextMenu->addItem(
new wxutil::StockIconTextMenuItem(_("Add property..."), wxART_PLUS),
- std::bind(&EntityInspector::_onAddKey, this)
+ std::bind(&EntityInspector::_onAddKey, this),
+ std::bind(&EntityInspector::_testAddKey, this)
);
_contextMenu->addItem(
new wxutil::StockIconTextMenuItem(_("Delete property"), wxART_MINUS),
@@ -301,22 +322,37 @@ void EntityInspector::createContextMenu()
_contextMenu->addSeparator();
_contextMenu->addItem(
- new wxutil::StockIconTextMenuItem(_("Copy Spawnarg"), wxART_COPY),
+ new wxutil::StockIconTextMenuItem(_("Copy Spawnarg(s)"), wxART_COPY),
std::bind(&EntityInspector::_onCopyKey, this),
std::bind(&EntityInspector::_testCopyKey, this)
);
_contextMenu->addItem(
- new wxutil::StockIconTextMenuItem(_("Cut Spawnarg"), wxART_CUT),
+ new wxutil::StockIconTextMenuItem(_("Cut Spawnarg(s)"), wxART_CUT),
std::bind(&EntityInspector::_onCutKey, this),
std::bind(&EntityInspector::_testCutKey, this)
);
_contextMenu->addItem(
- new wxutil::StockIconTextMenuItem(_("Paste Spawnarg"), wxART_PASTE),
+ new wxutil::StockIconTextMenuItem(_("Paste Spawnarg(s)"), wxART_PASTE),
std::bind(&EntityInspector::_onPasteKey, this),
std::bind(&EntityInspector::_testPasteKey, this)
);
}
+void EntityInspector::onRadiantStartup()
+{
+ // Add entity inspector to the group dialog
+ IGroupDialog::PagePtr page(new IGroupDialog::Page);
+
+ page->name = "entity";
+ page->windowLabel = _("Entity");
+ page->page = getWidget();
+ page->tabIcon = "cmenu_add_entity.png";
+ page->tabLabel = _("Entity");
+ page->position = IGroupDialog::Page::Position::EntityInspector;
+
+ GlobalGroupDialog().addPage(page);
+}
+
void EntityInspector::onRadiantShutdown()
{
// Remove all previously stored pane information
@@ -355,7 +391,8 @@ const StringSet& EntityInspector::getDependencies() const
{
static StringSet _dependencies;
- if (_dependencies.empty()) {
+ if (_dependencies.empty())
+ {
_dependencies.insert(MODULE_XMLREGISTRY);
_dependencies.insert(MODULE_UIMANAGER);
_dependencies.insert(MODULE_SELECTIONSYSTEM);
@@ -373,6 +410,9 @@ void EntityInspector::initialiseModule(const ApplicationContext& ctx)
{
construct();
+ GlobalRadiant().signal_radiantStarted().connect(
+ sigc::mem_fun(this, &EntityInspector::onRadiantStartup)
+ );
GlobalRadiant().signal_radiantShutdown().connect(
sigc::mem_fun(this, &EntityInspector::onRadiantShutdown)
);
@@ -422,12 +462,16 @@ wxWindow* EntityInspector::createTreeViewPane(wxWindow* parent)
_kvStore = new wxutil::TreeModel(_columns, true); // this is a list model
- _keyValueTreeView = wxutil::TreeView::CreateWithModel(treeViewPanel, _kvStore, wxDV_SINGLE);
+ _keyValueTreeView = wxutil::TreeView::CreateWithModel(treeViewPanel, _kvStore, wxDV_MULTIPLE);
// Search in both name and value columns
_keyValueTreeView->AddSearchColumn(_columns.name);
_keyValueTreeView->AddSearchColumn(_columns.value);
+ // Add the checkbox for boolean properties
+ _keyValueTreeView->AppendToggleColumn("", _columns.booleanValue.getColumnIndex(),
+ wxDATAVIEW_CELL_ACTIVATABLE, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT);
+
// Create the Property column (has an icon)
_keyValueTreeView->AppendIconTextColumn(_("Property"),
_columns.name.getColumnIndex(), wxDATAVIEW_CELL_INERT,
@@ -440,7 +484,7 @@ wxWindow* EntityInspector::createTreeViewPane(wxWindow* parent)
// Add the help icon
_helpColumn = _keyValueTreeView->AppendBitmapColumn(_("?"),
- _columns.helpIcon.getColumnIndex(), wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE);
+ _columns.helpIcon.getColumnIndex(), wxDATAVIEW_CELL_INERT, wxCOL_WIDTH_AUTOSIZE, wxALIGN_NOT);
_helpColumn->SetHidden(true);
// Used to update the help text
@@ -449,6 +493,11 @@ wxWindow* EntityInspector::createTreeViewPane(wxWindow* parent)
_keyValueTreeView->Connect(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU,
wxDataViewEventHandler(EntityInspector::_onContextMenu), NULL, this);
+ // When the toggle column is clicked to check/uncheck the box, the model's column value
+ // is directly changed by the wxWidgets event handlers. On model value change, this event is fired afterwards
+ _keyValueTreeView->Connect(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED,
+ wxDataViewEventHandler(EntityInspector::_onDataViewItemChanged), NULL, this);
+
wxBoxSizer* buttonHbox = new wxBoxSizer(wxHORIZONTAL);
// Pack in the key and value edit boxes
@@ -476,7 +525,14 @@ wxWindow* EntityInspector::createTreeViewPane(wxWindow* parent)
std::string EntityInspector::getSelectedKey()
{
- wxDataViewItem item = _keyValueTreeView->GetSelection();
+ wxDataViewItemArray selectedItems;
+ if (_keyValueTreeView->GetSelections(selectedItems) != 1)
+ {
+ // Multiple or nothing selected, return empty string
+ return std::string();
+ }
+
+ const wxDataViewItem& item = selectedItems.front();
if (!item.IsOk()) return "";
@@ -488,7 +544,14 @@ std::string EntityInspector::getSelectedKey()
std::string EntityInspector::getListSelection(const wxutil::TreeModel::Column& col)
{
- wxDataViewItem item = _keyValueTreeView->GetSelection();
+ wxDataViewItemArray selectedItems;
+ if (_keyValueTreeView->GetSelections(selectedItems) != 1)
+ {
+ // Multiple or nothing selected, return empty string
+ return std::string();
+ }
+
+ const wxDataViewItem& item = selectedItems.front();
if (!item.IsOk()) return "";
@@ -499,7 +562,14 @@ std::string EntityInspector::getListSelection(const wxutil::TreeModel::Column& c
bool EntityInspector::getListSelectionBool(const wxutil::TreeModel::Column& col)
{
- wxDataViewItem item = _keyValueTreeView->GetSelection();
+ wxDataViewItemArray selectedItems;
+ if (_keyValueTreeView->GetSelections(selectedItems) != 1)
+ {
+ // Multiple or nothing selected, return false
+ return false;
+ }
+
+ const wxDataViewItem& item = selectedItems.front();
if (!item.IsOk()) return false;
@@ -533,7 +603,7 @@ void EntityInspector::updateGUIElements()
// Disable the dialog and clear the TreeView
_editorFrame->Enable(false);
- _keyValueTreeView->Enable(false);
+ _keyValueTreeView->Enable(true); // leave the treeview enabled
_showInheritedCheckbox->Enable(false);
_showHelpColumnCheckbox->Enable(false);
}
@@ -550,70 +620,13 @@ void EntityInspector::selectionChanged(const scene::INodePtr& node, bool isCompo
requestIdleCallback();
}
-namespace
-{
-
- // SelectionSystem visitor to set a keyvalue on each entity, checking for
- // func_static-style name=model requirements
- class EntityKeySetter
- : public SelectionSystem::Visitor
- {
- // Key and value to set on all entities
- std::string _key;
- std::string _value;
-
- public:
-
- // Construct with key and value to set
- EntityKeySetter(const std::string& k, const std::string& v)
- : _key(k), _value(v)
- { }
-
- // Required visit function
- void visit(const scene::INodePtr& node) const
- {
- Entity* entity = Node_getEntity(node);
- if (entity)
- {
- // Check if we have a func_static-style entity
- std::string name = entity->getKeyValue("name");
- std::string model = entity->getKeyValue("model");
- bool isFuncType = (!name.empty() && name == model);
-
- // Set the actual value
- entity->setKeyValue(_key, _value);
-
- // Check for name key changes of func_statics
- if (isFuncType && _key == "name")
- {
- // Adapt the model key along with the name
- entity->setKeyValue("model", _value);
- }
- }
- else if (Node_isPrimitive(node)) {
- // We have a primitve node selected, check its parent
- scene::INodePtr parent(node->getParent());
-
- if (parent == NULL) return;
-
- Entity* parentEnt = Node_getEntity(parent);
-
- if (parentEnt != NULL) {
- // We have child primitive of an entity selected, the change
- // should go right into that parent entity
- parentEnt->setKeyValue(_key, _value);
- }
- }
- }
- };
-}
-
std::string EntityInspector::cleanInputString(const std::string &input)
{
std::string ret = input;
- boost::algorithm::replace_all( ret, "\n", "" );
- boost::algorithm::replace_all( ret, "\r", "" );
+ boost::algorithm::replace_all(ret, "\n", "");
+ boost::algorithm::replace_all(ret, "\r", "");
+
return ret;
}
@@ -628,44 +641,21 @@ void EntityInspector::setPropertyFromEntries()
_keyEntry->SetValue(key);
_valEntry->SetValue(val);
+ UndoableCommand cmd("entitySetProperty");
+
// Pass the call to the specialised routine
applyKeyValueToSelection(key, val);
}
void EntityInspector::applyKeyValueToSelection(const std::string& key, const std::string& val)
{
- // greebo: Instantiate a scoped object to make this operation undoable
- UndoableCommand command("entitySetProperty");
-
- if (key.empty()) {
- return;
- }
-
- if (key == "name") {
- // Check the global namespace if this change is ok
- scene::IMapRootNodePtr mapRoot = GlobalMapModule().getRoot();
- if (mapRoot != NULL) {
- INamespacePtr nspace = mapRoot->getNamespace();
-
- if (nspace != NULL && nspace->nameExists(val))
- {
- // name exists, cancel the change
- wxutil::Messagebox::ShowError(
- (boost::format(_("The name %s already exists in this map!")) % val).str());
- return;
- }
- }
- }
-
- // Detect classname changes
- if (key == "classname") {
- // Classname changes are handled in a special way
- selection::algorithm::setEntityClassname(val);
+ try
+ {
+ selection::algorithm::setEntityKeyvalue(key, val);
}
- else {
- // Regular key change, use EntityKeySetter to set value on all selected entities
- EntityKeySetter setter(key, val);
- GlobalSelectionSystem().foreachSelected(setter);
+ catch (std::runtime_error& ex)
+ {
+ wxutil::Messagebox::ShowError(ex.what());
}
}
@@ -716,6 +706,11 @@ void EntityInspector::_onAddKey()
}
}
+bool EntityInspector::_testAddKey()
+{
+ return !_selectedEntity.expired();
+}
+
void EntityInspector::_onDeleteKey()
{
assert(!_selectedEntity.expired());
@@ -733,6 +728,10 @@ void EntityInspector::_onDeleteKey()
bool EntityInspector::_testDeleteKey()
{
+ if (_selectedEntity.expired()) return false;
+
+ if (getSelectedKey().empty()) return false;
+
// Make sure the Delete item is only available for explicit
// (non-inherited) properties
if (getListSelectionBool(_columns.isInherited) == false)
@@ -743,6 +742,25 @@ bool EntityInspector::_testDeleteKey()
void EntityInspector::_onCopyKey()
{
+ wxDataViewItemArray selectedItems;
+ _keyValueTreeView->GetSelections(selectedItems);
+
+ if (selectedItems.Count() == 0) return;
+
+ _clipBoard.clear();
+
+ for (const wxDataViewItem& item : selectedItems)
+ {
+ wxutil::TreeModel::Row row(item, *_kvStore);
+
+ wxDataViewIconText iconAndName = static_cast<wxDataViewIconText>(row[_columns.name]);
+
+ std::string key = iconAndName.GetText().ToStdString();
+ std::string value = row[_columns.value];
+
+ _clipBoard.push_back(std::make_pair(key, value));
+ }
+#if 0
std::string key = getSelectedKey();
std::string value = getListSelection(_columns.value);
@@ -751,15 +769,47 @@ void EntityInspector::_onCopyKey()
_clipBoard.key = key;
_clipBoard.value = value;
}
+#endif
}
bool EntityInspector::_testCopyKey()
{
- return !getSelectedKey().empty();
+ return _keyValueTreeView->HasSelection();
}
void EntityInspector::_onCutKey()
{
+ wxDataViewItemArray selectedItems;
+ _keyValueTreeView->GetSelections(selectedItems);
+
+ if (selectedItems.Count() == 0) return;
+
+ assert(!_selectedEntity.expired());
+ Entity* selectedEntity = Node_getEntity(_selectedEntity.lock());
+
+ _clipBoard.clear();
+
+ for (const wxDataViewItem& item : selectedItems)
+ {
+ wxutil::TreeModel::Row row(item, *_kvStore);
+
+ wxDataViewIconText iconAndName = static_cast<wxDataViewIconText>(row[_columns.name]);
+
+ std::string key = iconAndName.GetText().ToStdString();
+ std::string value = row[_columns.value];
+
+ _clipBoard.push_back(std::make_pair(key, value));
+
+ // We don't delete any inherited key values
+ if (row[_columns.isInherited].getBool()) continue;
+
+ UndoableCommand cmd("cutProperty");
+
+ // Clear the key after copying
+ selectedEntity->setKeyValue(key, "");
+ }
+
+#if 0
std::string key = getSelectedKey();
std::string value = getListSelection(_columns.value);
@@ -776,10 +826,26 @@ void EntityInspector::_onCutKey()
// Clear the key after copying
selectedEntity->setKeyValue(key, "");
}
+#endif
}
bool EntityInspector::_testCutKey()
{
+ wxDataViewItemArray selectedItems;
+ _keyValueTreeView->GetSelections(selectedItems);
+
+ for (const wxDataViewItem& item : selectedItems)
+ {
+ wxutil::TreeModel::Row row(item, *_kvStore);
+
+ if (!row[_columns.isInherited].getBool())
+ {
+ return true; // we have at least one non-inherited value
+ }
+ }
+
+ return false;
+#if 0
// Make sure the Delete item is only available for explicit
// (non-inherited) properties
if (getListSelectionBool(_columns.isInherited) == false)
@@ -791,14 +857,21 @@ bool EntityInspector::_testCutKey()
{
return false;
}
+#endif
}
void EntityInspector::_onPasteKey()
{
- if (!_clipBoard.key.empty() && !_clipBoard.value.empty())
+ // greebo: Instantiate a scoped object to make this operation undoable
+ UndoableCommand command("entitySetProperties");
+
+ for (const KeyValuePair& kv : _clipBoard)
{
+ // skip empty entries
+ if (kv.first.empty() || kv.second.empty()) continue;
+
// Pass the call
- applyKeyValueToSelection(_clipBoard.key, _clipBoard.value);
+ applyKeyValueToSelection(kv.first, kv.second);
}
}
@@ -811,7 +884,7 @@ bool EntityInspector::_testPasteKey()
}
// Return true if the clipboard contains data
- return !_clipBoard.key.empty() && !_clipBoard.value.empty();
+ return !_clipBoard.empty();
}
// wxWidget callbacks
@@ -821,6 +894,45 @@ void EntityInspector::_onContextMenu(wxDataViewEvent& ev)
_contextMenu->show(_keyValueTreeView);
}
+void EntityInspector::_onDataViewItemChanged(wxDataViewEvent& ev)
+{
+ if (ev.GetDataViewColumn() != nullptr &&
+ static_cast<int>(ev.GetDataViewColumn()->GetModelColumn()) == _columns.booleanValue.getColumnIndex())
+ {
+ // Model value in the boolean column has changed, this means
+ // the user has clicked the checkbox, send the value to the entity/entities
+ wxutil::TreeModel::Row row(ev.GetItem(), *_kvStore);
+
+ wxDataViewIconText iconAndName = static_cast<wxDataViewIconText>(row[_columns.name]);
+
+ std::string key = iconAndName.GetText().ToStdString();
+ bool updatedValue = row[_columns.booleanValue].getBool();
+
+ UndoableCommand cmd("entitySetProperty");
+ applyKeyValueToSelection(key, updatedValue ? "1" : "0");
+
+ // Check if the property was an inherited one.
+ // The applyKeyValue function produced a non-inherited entry
+ // which should be visible once we're done
+ // Note: selecting the non-inherited property instead of this one
+ // is not as easy as it may appear, since the user is yet to release
+ // the mouse button (we're in the middle of the click event here)
+ // and the MouseUp handler will select this row again
+ if (row[_columns.isInherited].getBool())
+ {
+ _kvStore->ForeachNode([&](wxutil::TreeModel::Row& row)
+ {
+ wxDataViewIconText nameVal = static_cast<wxDataViewIconText>(row[_columns.name]);
+
+ if (nameVal.GetText() == key && !row[_columns.isInherited].getBool())
+ {
+ _keyValueTreeView->EnsureVisible(row.getItem());
+ }
+ });
+ }
+ }
+}
+
void EntityInspector::_onSetProperty(wxCommandEvent& ev)
{
setPropertyFromEntries();
@@ -890,57 +1002,70 @@ void EntityInspector::updateHelpText(const wxutil::TreeModel::Row& row)
// and making sure it refers to the currently-selected Entity.
void EntityInspector::_onTreeViewSelectionChanged(wxDataViewEvent& ev)
{
- ev.Skip();
+ ev.Skip();
- // Abort if called without a valid entity selection (may happen during
- // various cleanup operations).
- if (_selectedEntity.expired()) return;
+ // Abort if called without a valid entity selection (may happen during
+ // various cleanup operations).
+ if (_selectedEntity.expired()) return;
- wxutil::TreeModel::Row row(ev.GetItem(), *_kvStore);
+ wxDataViewItemArray selectedItems;
+ _keyValueTreeView->GetSelections(selectedItems);
- if (_showHelpColumnCheckbox->IsChecked())
- {
- updateHelpText(row);
- }
+ if (selectedItems.Count() == 1)
+ {
+ wxDataViewItem selectedItem = selectedItems.front();
- // Don't go further without a proper tree selection
- if (!ev.GetItem().IsOk()) return;
+ wxutil::TreeModel::Row row(selectedItem, *_kvStore);
- // Get the selected key and value in the tree view
- std::string key = getSelectedKey();
- std::string value = getListSelection(_columns.value);
+ if (_showHelpColumnCheckbox->IsChecked())
+ {
+ updateHelpText(row);
+ }
- // Get the type for this key if it exists, and the options
- PropertyParms parms = getPropertyParmsForKey(key);
+ // Don't go further without a proper tree selection
+ if (!selectedItem.IsOk()) return;
- Entity* selectedEntity = Node_getEntity(_selectedEntity.lock());
+ // Get the selected key and value in the tree view
+ std::string key = getSelectedKey();
+ std::string value = getListSelection(_columns.value);
- // If the type was not found, also try looking on the entity class
- if (parms.type.empty())
- {
- IEntityClassConstPtr eclass = selectedEntity->getEntityClass();
- parms.type = eclass->getAttribute(key).getType();
- }
+ // Get the type for this key if it exists, and the options
+ PropertyParms parms = getPropertyParmsForKey(key);
- // Construct and add a new PropertyEditor
- _currentPropertyEditor = PropertyEditorFactory::create(_editorFrame,
- parms.type, selectedEntity, key, parms.options);
+ Entity* selectedEntity = Node_getEntity(_selectedEntity.lock());
- if (_currentPropertyEditor)
- {
- // Don't use wxEXPAND to allow for horizontal centering, just add a 6 pixel border
- // Using wxALIGN_CENTER_HORIZONTAL will position the property editor's panel in the middle
- _editorFrame->GetSizer()->Add(_currentPropertyEditor->getWidget(), 1, wxALIGN_CENTER_HORIZONTAL | wxALL, 6);
- _editorFrame->GetSizer()->Layout();
- }
+ // If the type was not found, also try looking on the entity class
+ if (parms.type.empty())
+ {
+ IEntityClassConstPtr eclass = selectedEntity->getEntityClass();
+ parms.type = eclass->getAttribute(key).getType();
+ }
- // Update key and value entry boxes, but only if there is a key value. If
- // there is no selection we do not clear the boxes, to allow keyval copying
- // between entities.
- if (!key.empty())
+ // Construct and add a new PropertyEditor
+ _currentPropertyEditor = PropertyEditorFactory::create(_editorFrame,
+ parms.type, selectedEntity, key, parms.options);
+
+ if (_currentPropertyEditor)
+ {
+ // Don't use wxEXPAND to allow for horizontal centering, just add a 6 pixel border
+ // Using wxALIGN_CENTER_HORIZONTAL will position the property editor's panel in the middle
+ _editorFrame->GetSizer()->Add(_currentPropertyEditor->getWidget(), 1, wxALIGN_CENTER_HORIZONTAL | wxALL, 6);
+ _editorFrame->GetSizer()->Layout();
+ }
+
+ // Update key and value entry boxes, but only if there is a key value. If
+ // there is no selection we do not clear the boxes, to allow keyval copying
+ // between entities.
+ if (!key.empty())
+ {
+ _keyEntry->SetValue(key);
+ _valEntry->SetValue(value);
+ }
+ }
+ else if (selectedItems.Count() > 1)
{
- _keyEntry->SetValue(key);
- _valEntry->SetValue(value);
+ // When multiple items are selected, clear the property editor
+ _currentPropertyEditor.reset();
}
}
@@ -986,6 +1111,17 @@ void EntityInspector::addClassAttribute(const EntityClassAttribute& a)
row[_columns.name] = wxVariant(wxDataViewIconText(a.getName(), _emptyIcon));
row[_columns.value] = a.getValue();
+ // Inherited values have an inactive checkbox, so assign a false value and disable
+ if (a.getType() == "bool")
+ {
+ row[_columns.booleanValue] = a.getValue() == "1";
+ }
+ else
+ {
+ row[_columns.booleanValue] = false;
+ row[_columns.booleanValue].setEnabled(false);
+ }
+
row[_columns.name] = grey;
row[_columns.value] = grey;
diff --git a/radiant/ui/einspector/EntityInspector.h b/radiant/ui/einspector/EntityInspector.h
index 5d65818..afe667e 100644
--- a/radiant/ui/einspector/EntityInspector.h
+++ b/radiant/ui/einspector/EntityInspector.h
@@ -57,7 +57,8 @@ public:
value(add(wxutil::TreeModel::Column::String)),
isInherited(add(wxutil::TreeModel::Column::Boolean)),
helpIcon(add(wxutil::TreeModel::Column::Icon)),
- hasHelpText(add(wxutil::TreeModel::Column::Boolean))
+ hasHelpText(add(wxutil::TreeModel::Column::Boolean)),
+ booleanValue(add(wxutil::TreeModel::Column::Boolean))
{}
wxutil::TreeModel::Column name;
@@ -65,6 +66,7 @@ public:
wxutil::TreeModel::Column isInherited;
wxutil::TreeModel::Column helpIcon;
wxutil::TreeModel::Column hasHelpText;
+ wxutil::TreeModel::Column booleanValue;
};
private:
@@ -129,15 +131,9 @@ private:
IPropertyEditorPtr _currentPropertyEditor;
// The clipboard for spawnargs
- struct ClipBoard
- {
- std::string key;
- std::string value;
-
- bool empty() const {
- return key.empty();
- }
- } _clipBoard;
+ typedef std::pair<std::string, std::string> KeyValuePair;
+ typedef std::vector<KeyValuePair> ClipBoard;
+ ClipBoard _clipBoard;
// Data structure to store the type (vector3, text etc) and the options
// string for a single property.
@@ -174,6 +170,7 @@ private:
void _onCutKey();
void _onPasteKey();
+ bool _testAddKey();
bool _testDeleteKey();
bool _testCopyKey();
bool _testCutKey();
@@ -186,6 +183,7 @@ private:
void _onToggleShowHelpIcons(wxCommandEvent& ev);
void _onTreeViewSelectionChanged(wxDataViewEvent& ev);
void _onContextMenu(wxDataViewEvent& ev);
+ void _onDataViewItemChanged(wxDataViewEvent& ev);
void updateHelpText(const wxutil::TreeModel::Row& row);
static std::string cleanInputString( const std::string& );
@@ -237,6 +235,7 @@ public:
IPropertyEditorPtr getRegisteredPropertyEditor(const std::string& key);
void unregisterPropertyEditor(const std::string& key);
+ void onRadiantStartup();
void onRadiantShutdown();
// Gets called after an undo operation
diff --git a/radiant/ui/einspector/EntityPropertyEditor.cpp b/radiant/ui/einspector/EntityPropertyEditor.cpp
index 1aecef0..1b85f75 100644
--- a/radiant/ui/einspector/EntityPropertyEditor.cpp
+++ b/radiant/ui/einspector/EntityPropertyEditor.cpp
@@ -32,6 +32,11 @@ EntityPropertyEditor::EntityPropertyEditor(wxWindow* parent, Entity* entity, con
PropertyEditorFactory::getBitmapFor("entity"));
}
+void EntityPropertyEditor::updateFromEntity()
+{
+ // nothing to do
+}
+
void EntityPropertyEditor::onBrowseButtonClick()
{
// Use a new dialog window to get a selection from the user
diff --git a/radiant/ui/einspector/EntityPropertyEditor.h b/radiant/ui/einspector/EntityPropertyEditor.h
index c62faea..eecd534 100644
--- a/radiant/ui/einspector/EntityPropertyEditor.h
+++ b/radiant/ui/einspector/EntityPropertyEditor.h
@@ -27,10 +27,12 @@ public:
// PropertyEditorFactory
EntityPropertyEditor();
+ void updateFromEntity() override;
+
// Create a new EntityPropertyEditor
virtual IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new EntityPropertyEditor(parent, entity, name));
}
diff --git a/radiant/ui/einspector/FloatPropertyEditor.cpp b/radiant/ui/einspector/FloatPropertyEditor.cpp
index 1078977..ca2eb90 100644
--- a/radiant/ui/einspector/FloatPropertyEditor.cpp
+++ b/radiant/ui/einspector/FloatPropertyEditor.cpp
@@ -19,7 +19,7 @@ namespace ui
{
FloatPropertyEditor::FloatPropertyEditor() :
- _spinCtrl(NULL)
+ _spinCtrl(nullptr)
{}
// Main constructor
@@ -27,7 +27,7 @@ FloatPropertyEditor::FloatPropertyEditor(wxWindow* parent, Entity* entity,
const std::string& key,
const std::string& options)
: PropertyEditor(entity),
- _spinCtrl(NULL),
+ _spinCtrl(nullptr),
_key(key)
{
// Construct the main widget (will be managed by the base class)
@@ -65,14 +65,7 @@ FloatPropertyEditor::FloatPropertyEditor(wxWindow* parent, Entity* entity,
_spinCtrl->SetMinSize(wxSize(75, -1));
// Set the initial value if the entity has one
- float value = 0;
- try
- {
- value = boost::lexical_cast<float>(_entity->getKeyValue(_key));
- }
- catch (boost::bad_lexical_cast&) { }
-
- _spinCtrl->SetValue(value);
+ updateFromEntity();
// Create and pack in the Apply button
wxButton* applyButton = new wxButton(mainVBox, wxID_APPLY, _("Apply..."));
@@ -82,6 +75,21 @@ FloatPropertyEditor::FloatPropertyEditor(wxWindow* parent, Entity* entity,
mainVBox->GetSizer()->Add(applyButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 6);
}
+void FloatPropertyEditor::updateFromEntity()
+{
+ if (_spinCtrl == nullptr) return;
+
+ float value = 0;
+
+ try
+ {
+ value = boost::lexical_cast<float>(_entity->getKeyValue(_key));
+ }
+ catch (boost::bad_lexical_cast&) {}
+
+ _spinCtrl->SetValue(value);
+}
+
void FloatPropertyEditor::_onApply(wxCommandEvent& ev)
{
float value = static_cast<float>(_spinCtrl->GetValue());
diff --git a/radiant/ui/einspector/FloatPropertyEditor.h b/radiant/ui/einspector/FloatPropertyEditor.h
index 243621f..ffa94eb 100644
--- a/radiant/ui/einspector/FloatPropertyEditor.h
+++ b/radiant/ui/einspector/FloatPropertyEditor.h
@@ -38,12 +38,14 @@ public:
*/
FloatPropertyEditor(wxWindow* parent, Entity*, const std::string&, const std::string&);
+ void updateFromEntity() override;
+
/**
* Virtual PropertyEditor clone method.
*/
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(
new FloatPropertyEditor(parent, entity, name, options)
diff --git a/radiant/ui/einspector/ModelPropertyEditor.h b/radiant/ui/einspector/ModelPropertyEditor.h
index 97d7756..ff8cf68 100644
--- a/radiant/ui/einspector/ModelPropertyEditor.h
+++ b/radiant/ui/einspector/ModelPropertyEditor.h
@@ -36,7 +36,7 @@ public:
// Clone method for virtual construction
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(
new ModelPropertyEditor(parent, entity, name, options)
diff --git a/radiant/ui/einspector/PropertyEditor.h b/radiant/ui/einspector/PropertyEditor.h
index 6575afa..f272c45 100644
--- a/radiant/ui/einspector/PropertyEditor.h
+++ b/radiant/ui/einspector/PropertyEditor.h
@@ -85,7 +85,12 @@ public:
virtual ~PropertyEditor();
// IPropertyEditor implementation
- wxPanel* getWidget();
+ wxPanel* getWidget() override;
+
+ virtual void updateFromEntity()
+ {
+ // nothing by default, override in subclasses if needed
+ }
};
} // namespace
diff --git a/radiant/ui/einspector/SkinPropertyEditor.h b/radiant/ui/einspector/SkinPropertyEditor.h
index b8161f6..821901a 100644
--- a/radiant/ui/einspector/SkinPropertyEditor.h
+++ b/radiant/ui/einspector/SkinPropertyEditor.h
@@ -36,7 +36,7 @@ public:
// Clone method for virtual construction
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new SkinPropertyEditor(parent, entity, name, options));
}
diff --git a/radiant/ui/einspector/SoundPropertyEditor.h b/radiant/ui/einspector/SoundPropertyEditor.h
index d1b53bc..fdf9e07 100644
--- a/radiant/ui/einspector/SoundPropertyEditor.h
+++ b/radiant/ui/einspector/SoundPropertyEditor.h
@@ -32,7 +32,7 @@ public:
// Clone method for virtual construction
IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(
new SoundPropertyEditor(parent, entity, name, options)
diff --git a/radiant/ui/einspector/TexturePropertyEditor.h b/radiant/ui/einspector/TexturePropertyEditor.h
index 790ef89..9a4be74 100644
--- a/radiant/ui/einspector/TexturePropertyEditor.h
+++ b/radiant/ui/einspector/TexturePropertyEditor.h
@@ -38,7 +38,7 @@ public:
// Create a new TexturePropertyEditor
virtual IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(
new TexturePropertyEditor(parent, entity, name, options)
diff --git a/radiant/ui/einspector/Vector3PropertyEditor.cpp b/radiant/ui/einspector/Vector3PropertyEditor.cpp
index 1c1367d..3c9f8e5 100644
--- a/radiant/ui/einspector/Vector3PropertyEditor.cpp
+++ b/radiant/ui/einspector/Vector3PropertyEditor.cpp
@@ -65,7 +65,12 @@ Vector3PropertyEditor::Vector3PropertyEditor(wxWindow* parent, Entity* entity,
mainVBox->GetSizer()->Add(applyButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 6);
// Populate the spin boxes from the keyvalue
- setWidgetsFromKey(_entity->getKeyValue(name));
+ updateFromEntity();
+}
+
+void Vector3PropertyEditor::updateFromEntity()
+{
+ setWidgetsFromKey(_entity->getKeyValue(_key));
}
void Vector3PropertyEditor::setWidgetsFromKey(const std::string& val)
diff --git a/radiant/ui/einspector/Vector3PropertyEditor.h b/radiant/ui/einspector/Vector3PropertyEditor.h
index 8d65837..69d2fbf 100644
--- a/radiant/ui/einspector/Vector3PropertyEditor.h
+++ b/radiant/ui/einspector/Vector3PropertyEditor.h
@@ -39,10 +39,12 @@ public:
// Construct a blank TextPropertyEditor for use in the PropertyEditorFactory
Vector3PropertyEditor();
+ void updateFromEntity() override;
+
// Create a new TextPropertyEditor
virtual IPropertyEditorPtr createNew(wxWindow* parent, Entity* entity,
const std::string& name,
- const std::string& options)
+ const std::string& options) override
{
return PropertyEditorPtr(new Vector3PropertyEditor(parent, entity, name));
}
diff --git a/radiant/ui/layers/LayerControl.cpp b/radiant/ui/layers/LayerControl.cpp
index ceb265e..db5a735 100644
--- a/radiant/ui/layers/LayerControl.cpp
+++ b/radiant/ui/layers/LayerControl.cpp
@@ -125,7 +125,7 @@ void LayerControl::onDelete(wxCommandEvent& ev)
{
// Ask the about the deletion
std::string msg = _("Do you really want to delete this layer?");
- msg += "\n<b>" + scene::getLayerSystem().getLayerName(_layerID) + "</b>";
+ msg += "\n" + scene::getLayerSystem().getLayerName(_layerID);
IDialogPtr box = GlobalDialogManager().createMessageBox(
_("Confirm Layer Deletion"), msg, IDialog::MESSAGE_ASK
diff --git a/radiant/ui/mainframe/EmbeddedLayout.cpp b/radiant/ui/mainframe/EmbeddedLayout.cpp
index 72e078f..9653009 100644
--- a/radiant/ui/mainframe/EmbeddedLayout.cpp
+++ b/radiant/ui/mainframe/EmbeddedLayout.cpp
@@ -77,6 +77,7 @@ void EmbeddedLayout::activate()
page->page = textureBrowser;
page->tabIcon = "icon_texture.png";
page->tabLabel = _("Textures");
+ page->position = IGroupDialog::Page::Position::TextureBrowser;
GlobalGroupDialog().addPage(page);
}
diff --git a/radiant/ui/mainframe/FloatingLayout.cpp b/radiant/ui/mainframe/FloatingLayout.cpp
index 228b597..118dc1f 100644
--- a/radiant/ui/mainframe/FloatingLayout.cpp
+++ b/radiant/ui/mainframe/FloatingLayout.cpp
@@ -60,6 +60,7 @@ void FloatingLayout::activate()
page->page = textureBrowser;
page->tabIcon = "icon_texture.png";
page->tabLabel = _("Textures");
+ page->position = IGroupDialog::Page::Position::TextureBrowser;
GlobalGroupDialog().addPage(page);
}
diff --git a/radiant/ui/mainframe/MainFrame.cpp b/radiant/ui/mainframe/MainFrame.cpp
index 72e1ad1..3347637 100644
--- a/radiant/ui/mainframe/MainFrame.cpp
+++ b/radiant/ui/mainframe/MainFrame.cpp
@@ -2,35 +2,26 @@
#include "i18n.h"
#include "RadiantModule.h"
-#include "iuimanager.h"
-#include "idialogmanager.h"
#include "igroupdialog.h"
#include "ieventmanager.h"
+#include "iuimanager.h"
#include "ipreferencesystem.h"
-#include "igrid.h"
#include "ientityinspector.h"
#include "iorthoview.h"
+#include "iregistry.h"
-#include "ui/splash/Splash.h"
-#include "ui/menu/FiltersMenu.h"
#include "log/Console.h"
#include "xyview/GlobalXYWnd.h"
#include "ui/mediabrowser/MediaBrowser.h"
-#include "ui/texturebrowser/TextureBrowser.h"
-#include "ui/layers/LayerControlDialog.h"
-#include "ui/overlay/Overlay.h"
#include "camera/GlobalCamera.h"
-#include "camera/CameraSettings.h"
-#include "selection/shaderclipboard/ShaderClipboard.h"
#include "registry/registry.h"
-#include "map/AutoSaver.h"
-#include "brush/BrushModule.h"
#include "wxutil/MultiMonitor.h"
#include "ui/mainframe/ScreenUpdateBlocker.h"
#include "ui/mainframe/EmbeddedLayout.h"
#include "ui/mainframe/TopLevelFrame.h"
+#include "map/Map.h"
#include "modulesystem/StaticModule.h"
#include <functional>
@@ -57,7 +48,7 @@ namespace ui
MainFrame::MainFrame() :
_topLevelWindow(NULL),
- _screenUpdatesEnabled(true)
+ _screenUpdatesEnabled(false) // not enabled until constructed
{}
// RegisterableModule implementation
@@ -78,8 +69,8 @@ const StringSet& MainFrame::getDependencies() const
_dependencies.insert(MODULE_PREFERENCESYSTEM);
_dependencies.insert(MODULE_EVENTMANAGER);
_dependencies.insert(MODULE_COMMANDSYSTEM);
- _dependencies.insert(MODULE_UIMANAGER);
_dependencies.insert(MODULE_ORTHOVIEWMANAGER);
+ _dependencies.insert(MODULE_CAMERA);
}
return _dependencies;
@@ -90,7 +81,7 @@ void MainFrame::initialiseModule(const ApplicationContext& ctx)
rMessage() << "MainFrame::initialiseModule called." << std::endl;
// Add another page for Multi-Monitor stuff
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Multi Monitor"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Multi Monitor"));
// Initialise the registry, if no key is set
if (GlobalRegistry().get(RKEY_MULTIMON_START_MONITOR).empty())
@@ -109,7 +100,7 @@ void MainFrame::initialiseModule(const ApplicationContext& ctx)
);
}
- page->appendCombo(_("Start DarkRadiant on monitor"), RKEY_MULTIMON_START_MONITOR, list);
+ page.appendCombo(_("Start DarkRadiant on monitor"), RKEY_MULTIMON_START_MONITOR, list);
// Add the toggle max/min command for floating windows
GlobalCommandSystem().addCommand("ToggleFullScreenCamera",
@@ -128,9 +119,9 @@ void MainFrame::initialiseModule(const ApplicationContext& ctx)
if (dwmEnableComposition)
{
// Add a page for Desktop Composition stuff
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Compatibility"));
+ IPreferencePage& compatPage = GlobalPreferenceSystem().getPage(_("Settings/Compatibility"));
- page->appendCheckBox("", _("Disable Windows Desktop Composition"),
+ compatPage.appendCheckBox(_("Disable Windows Desktop Composition"),
RKEY_DISABLE_WIN_DESKTOP_COMP);
GlobalRegistry().signalForKey(RKEY_DISABLE_WIN_DESKTOP_COMP).connect(
@@ -149,6 +140,8 @@ void MainFrame::initialiseModule(const ApplicationContext& ctx)
void MainFrame::shutdownModule()
{
rMessage() << "MainFrame::shutdownModule called." << std::endl;
+
+ disableScreenUpdates();
}
void MainFrame::keyChanged()
@@ -226,6 +219,8 @@ void MainFrame::construct()
// register the commands
GlobalMainFrameLayoutManager().registerCommands();
+ enableScreenUpdates();
+
updateAllWindows();
}
@@ -253,12 +248,6 @@ void MainFrame::preDestructionCleanup()
// Broadcast shutdown event to RadiantListeners
radiant::getGlobalRadiant()->broadcastShutdownEvent();
-
- // Destroy the Overlay instance
- Overlay::destroyInstance();
-
- // Stop the AutoSaver class from being called
- map::AutoSaver().stopTimer();
}
void MainFrame::onTopLevelFrameClose(wxCloseEvent& ev)
@@ -373,17 +362,6 @@ void MainFrame::create()
/* Construct the Group Dialog. This is the tabbed window that contains
* a number of pages - usually Entities, Textures and possibly Console.
*/
- // Add entity inspector widget
- IGroupDialog::PagePtr entityInspectorPage(new IGroupDialog::Page);
-
- entityInspectorPage->name = "entity";
- entityInspectorPage->windowLabel = _("Entity");
- entityInspectorPage->page = GlobalEntityInspector().getWidget();
- entityInspectorPage->tabIcon = "cmenu_add_entity.png";
- entityInspectorPage->tabLabel = _("Entity");
-
- GlobalGroupDialog().addPage(entityInspectorPage);
-
// Add the Media Browser page
IGroupDialog::PagePtr mediaBrowserPage(new IGroupDialog::Page);
@@ -392,6 +370,7 @@ void MainFrame::create()
mediaBrowserPage->page = MediaBrowser::getInstance().getWidget();
mediaBrowserPage->tabIcon = "folder16.png";
mediaBrowserPage->tabLabel = _("Media");
+ mediaBrowserPage->position = IGroupDialog::Page::Position::MediaBrowser;
GlobalGroupDialog().addPage(mediaBrowserPage);
@@ -403,21 +382,12 @@ void MainFrame::create()
consolePage->page = new Console(getWxTopLevelWindow());
consolePage->tabIcon = "iconConsole16.png";
consolePage->tabLabel = _("Console");
+ consolePage->position = IGroupDialog::Page::Position::Console;
GlobalGroupDialog().addPage(consolePage);
// Load the previous window settings from the registry
restoreWindowPosition();
-
- _topLevelWindow->Show();
-
- // Start the autosave timer so that it can periodically check the map for changes
- map::AutoSaver().startTimer();
-
- // Initialise the shaderclipboard
- GlobalShaderClipboard().clear();
-
- LayerControlDialog::init();
}
void MainFrame::saveWindowPosition()
@@ -449,6 +419,8 @@ void MainFrame::disableScreenUpdates() {
void MainFrame::updateAllWindows(bool force)
{
+ if (!_screenUpdatesEnabled) return;
+
if (force)
{
GlobalCamera().forceDraw();
diff --git a/radiant/ui/mainframe/MainFrame.h b/radiant/ui/mainframe/MainFrame.h
index 2d2bcb8..adcf0c1 100644
--- a/radiant/ui/mainframe/MainFrame.h
+++ b/radiant/ui/mainframe/MainFrame.h
@@ -3,7 +3,6 @@
#include <map>
#include "icommandsystem.h"
#include "imainframe.h"
-#include "iregistry.h"
#include "imainframelayout.h"
#include "wxutil/WindowPosition.h"
diff --git a/radiant/ui/mainframe/ScreenUpdateBlocker.cpp b/radiant/ui/mainframe/ScreenUpdateBlocker.cpp
index 1416d46..0b0ea89 100644
--- a/radiant/ui/mainframe/ScreenUpdateBlocker.cpp
+++ b/radiant/ui/mainframe/ScreenUpdateBlocker.cpp
@@ -1,7 +1,6 @@
#include "ScreenUpdateBlocker.h"
#include "iradiant.h"
-#include "map/AutoSaver.h"
#include "imainframe.h"
#include <wx/app.h>
@@ -42,10 +41,7 @@ ScreenUpdateBlocker::ScreenUpdateBlocker(const std::string& title, const std::st
Fit();
CenterOnParent();
- // Stop the autosaver
- map::AutoSaver().stopTimer();
-
- // Set the "screen updates disabled" flag
+ // Set the "screen updates disabled" flag (also disables autosaver)
GlobalMainFrame().disableScreenUpdates();
// Connect the realize signal to remove the window decorations
@@ -90,9 +86,6 @@ ScreenUpdateBlocker::~ScreenUpdateBlocker()
// Re-draw the scene to clear any artefacts in the buffer
GlobalMainFrame().updateAllWindows();
-
- // Start the autosaver again
- map::AutoSaver().startTimer();
}
void ScreenUpdateBlocker::pulse()
diff --git a/radiant/ui/mainframe/SplitPaneLayout.cpp b/radiant/ui/mainframe/SplitPaneLayout.cpp
index a71da2b..e0d877c 100644
--- a/radiant/ui/mainframe/SplitPaneLayout.cpp
+++ b/radiant/ui/mainframe/SplitPaneLayout.cpp
@@ -112,6 +112,7 @@ void SplitPaneLayout::constructLayout()
page->page = textureBrowser;
page->tabIcon = "icon_texture.png";
page->tabLabel = _("Textures");
+ page->position = IGroupDialog::Page::Position::TextureBrowser;
GlobalGroupDialog().addPage(page);
}
diff --git a/radiant/ui/mediabrowser/MediaBrowser.cpp b/radiant/ui/mediabrowser/MediaBrowser.cpp
index cfe9de0..497c3a3 100644
--- a/radiant/ui/mediabrowser/MediaBrowser.cpp
+++ b/radiant/ui/mediabrowser/MediaBrowser.cpp
@@ -695,8 +695,8 @@ void MediaBrowser::toggle(const cmd::ArgumentList& args)
void MediaBrowser::registerCommandsAndPreferences()
{
// Add a page to the given group
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Media Browser"));
- page->appendCheckBox("", _("Load media tree at startup"), RKEY_MEDIA_BROWSER_PRELOAD);
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Media Browser"));
+ page.appendCheckBox(_("Load media tree at startup"), RKEY_MEDIA_BROWSER_PRELOAD);
GlobalCommandSystem().addCommand("ToggleMediaBrowser", toggle);
GlobalEventManager().addCommand("ToggleMediaBrowser", "ToggleMediaBrowser");
diff --git a/radiant/ui/mru/MRU.cpp b/radiant/ui/mru/MRU.cpp
index ff547a4..478e54b 100644
--- a/radiant/ui/mru/MRU.cpp
+++ b/radiant/ui/mru/MRU.cpp
@@ -122,10 +122,10 @@ void MRU::keyChanged()
// Construct the MRU preference page and add it to the given group
void MRU::constructPreferences()
{
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Map Files"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Map Files"));
- page->appendEntry(_("Number of most recently used files"), RKEY_MRU_LENGTH);
- page->appendCheckBox("", _("Open last map on startup"), RKEY_LOAD_LAST_MAP);
+ page.appendEntry(_("Number of most recently used files"), RKEY_MRU_LENGTH);
+ page.appendCheckBox(_("Open last map on startup"), RKEY_LOAD_LAST_MAP);
}
void MRU::initialise()
diff --git a/radiant/ui/ortho/OrthoContextMenu.cpp b/radiant/ui/ortho/OrthoContextMenu.cpp
index 0e0ea2a..7db828f 100644
--- a/radiant/ui/ortho/OrthoContextMenu.cpp
+++ b/radiant/ui/ortho/OrthoContextMenu.cpp
@@ -146,7 +146,7 @@ void OrthoContextMenu::analyseSelection()
GlobalSelectionSystem().foreachSelected(walker);
_selectionInfo.onlyGroupsSelected = walker.onlyGroupsAreSelected();
- _selectionInfo.singleGroupSelected = walker.selectedGroupCount() == 1 && !node_is_worldspawn(walker.getFirstSelectedGroupNode());
+ _selectionInfo.singleGroupSelected = walker.selectedGroupCount() == 1 && !Node_isWorldspawn(walker.getFirstSelectedGroupNode());
// Create a ModelFinder and check whether only models were selected
selection::algorithm::ModelFinder visitor;
@@ -234,7 +234,7 @@ bool OrthoContextMenu::checkRevertToWorldspawnPartial()
{
scene::INodePtr parent = node->getParent();
- return parent != NULL && scene::hasChildPrimitives(parent) && !node_is_worldspawn(parent);
+ return parent != NULL && scene::hasChildPrimitives(parent) && !Node_isWorldspawn(parent);
}
}
@@ -583,11 +583,12 @@ void OrthoContextMenu::constructMenu()
addSectionItems(SECTION_CREATE, true); // no spacer for first category
addSectionItems(SECTION_ACTION);
+ addSectionItems(SECTION_SELECTION_GROUPS);
addSectionItems(SECTION_LAYER);
// Add the rest of the sections
for (MenuSections::const_iterator sec = _sections.lower_bound(SECTION_LAYER+1);
- sec != _sections.end(); )
+ sec != _sections.end(); ++sec)
{
addSectionItems(sec->first);
}
diff --git a/radiant/ui/overlay/Overlay.cpp b/radiant/ui/overlay/Overlay.cpp
index fd95e73..7a2f36b 100644
--- a/radiant/ui/overlay/Overlay.cpp
+++ b/radiant/ui/overlay/Overlay.cpp
@@ -52,6 +52,7 @@ void Overlay::observeKey(const std::string& key)
void Overlay::onRadiantShutdown()
{
_texture = TexturePtr();
+ destroyInstance();
}
void Overlay::destroyInstance() {
diff --git a/radiant/ui/patch/PatchInspector.cpp b/radiant/ui/patch/PatchInspector.cpp
index 28b4fdc..8c170b7 100644
--- a/radiant/ui/patch/PatchInspector.cpp
+++ b/radiant/ui/patch/PatchInspector.cpp
@@ -365,7 +365,7 @@ void PatchInspector::rescanSelection()
if (tess.x() == UINT_MAX)
{
// Not initialised yet, take these values for starters
- tessIsFixed = p.subdivionsFixed();
+ tessIsFixed = p.subdivisionsFixed();
tess = p.getSubdivisions();
}
else
@@ -373,7 +373,7 @@ void PatchInspector::rescanSelection()
// We already have a pair of divisions, compare
Subdivisions otherTess = p.getSubdivisions();
- if (tessIsFixed != p.subdivionsFixed() || otherTess != tess)
+ if (tessIsFixed != p.subdivisionsFixed() || otherTess != tess)
{
// Our journey ends here, we cannot find a pair of tesselations
// for all selected patches or the same fixed/variable status
diff --git a/radiant/ui/prefabselector/PrefabSelector.cpp b/radiant/ui/prefabselector/PrefabSelector.cpp
index 39003b6..9df19c1 100644
--- a/radiant/ui/prefabselector/PrefabSelector.cpp
+++ b/radiant/ui/prefabselector/PrefabSelector.cpp
@@ -14,6 +14,7 @@
#include <sstream>
#include "string/convert.h"
#include "registry/registry.h"
+#include "registry/Widgets.h"
#include "os/path.h"
#include <wx/button.h>
@@ -47,6 +48,7 @@ namespace
const std::string RKEY_LAST_CUSTOM_PREFAB_PATH = RKEY_BASE + "lastPrefabPath";
const std::string RKEY_RECENT_PREFAB_PATHS = RKEY_BASE + "recentPaths";
+ const std::string RKEY_INSERT_AS_GROUP = RKEY_BASE + "insertAsGroup";
}
// Constructor.
@@ -62,7 +64,8 @@ PrefabSelector::PrefabSelector() :
_useCustomPath(nullptr),
_useRecentPath(nullptr),
_recentPathSelector(nullptr),
- _customPath(nullptr)
+ _customPath(nullptr),
+ _insertAsGroupBox(nullptr)
{
SetSizer(new wxBoxSizer(wxVERTICAL));
@@ -98,7 +101,16 @@ PrefabSelector::PrefabSelector() :
reloadButton->Connect(wxEVT_BUTTON, wxCommandEventHandler(PrefabSelector::onRescanPrefabs), NULL, this);
buttonSizer->Prepend(reloadButton, 0, wxRIGHT, 32);
- vbox->Add(buttonSizer, 0, wxALIGN_RIGHT | wxTOP, 12);
+
+ _insertAsGroupBox = new wxCheckBox(this, wxID_ANY, _("Create Group out of Prefab parts"));
+ registry::bindWidget(_insertAsGroupBox, RKEY_INSERT_AS_GROUP);
+
+ wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
+
+ hbox->Add(_insertAsGroupBox, 1, wxALL, 6);
+ hbox->Add(buttonSizer, 0);
+
+ vbox->Add(hbox, 0, wxEXPAND | wxTOP, 12);
// Set the default size of the window
_position.connect(this);
@@ -297,7 +309,7 @@ void PrefabSelector::onRadiantShutdown()
InstancePtr().reset();
}
-std::string PrefabSelector::ChoosePrefab(const std::string& curPrefab)
+PrefabSelector::Result PrefabSelector::ChoosePrefab(const std::string& curPrefab)
{
// Use the parameter only if it's not empty
if (!curPrefab.empty())
@@ -305,11 +317,15 @@ std::string PrefabSelector::ChoosePrefab(const std::string& curPrefab)
Instance()._lastPrefab = curPrefab;
}
- std::string returnValue = "";
+ Result returnValue;
+
+ returnValue.insertAsGroup = false;
+ returnValue.prefabPath = "";
if (Instance().ShowModal() == wxID_OK)
{
- returnValue = Instance().getSelectedValue(Instance()._columns.vfspath);
+ returnValue.prefabPath = Instance().getSelectedValue(Instance()._columns.vfspath);
+ returnValue.insertAsGroup = Instance().getInsertAsGroup();
}
Instance().Hide();
@@ -432,6 +448,11 @@ std::string PrefabSelector::getSelectedValue(const wxutil::TreeModel::Column& co
return row[col];
}
+bool PrefabSelector::getInsertAsGroup()
+{
+ return _insertAsGroupBox->GetValue();
+}
+
void PrefabSelector::clearPreview()
{
// NULLify the preview map root on failure
@@ -461,9 +482,9 @@ void PrefabSelector::handleSelectionChange()
std::string prefabPath = row[_columns.vfspath];
- _mapResource = GlobalMapResourceManager().capture(prefabPath);
+ _mapResource = GlobalMapResourceManager().loadFromPath(prefabPath);
- if (_mapResource == NULL)
+ if (!_mapResource)
{
clearPreview();
return;
@@ -475,14 +496,14 @@ void PrefabSelector::handleSelectionChange()
// getting stuck in the "drag filename" operation
registry::ScopedKeyChanger<bool> changer(
RKEY_MAP_SUPPRESS_LOAD_STATUS_DIALOG, true
- );
+ );
if (_mapResource->load())
{
// Get the node from the resource
scene::IMapRootNodePtr root = _mapResource->getNode();
- assert(root != NULL);
+ assert(root);
// Set the new rootnode
_preview->setRootNode(root);
diff --git a/radiant/ui/prefabselector/PrefabSelector.h b/radiant/ui/prefabselector/PrefabSelector.h
index 6b5da16..ed2c829 100644
--- a/radiant/ui/prefabselector/PrefabSelector.h
+++ b/radiant/ui/prefabselector/PrefabSelector.h
@@ -15,6 +15,7 @@
#include <string>
#include <wx/combobox.h>
+class wxCheckBox;
class wxSizer;
class wxRadioButton;
@@ -46,6 +47,12 @@ public:
wxutil::TreeModel::Column isFolder; // whether this is a folder
};
+ struct Result
+ {
+ std::string prefabPath; // VFS path of the prefab
+ bool insertAsGroup; // whether to insert the prefab as group
+ };
+
private:
wxPanel* _dialogPanel;
@@ -80,6 +87,7 @@ private:
wxRadioButton* _useRecentPath;
wxComboBox* _recentPathSelector;
wxutil::PathEntry* _customPath;
+ wxCheckBox* _insertAsGroupBox;
std::list<std::string> _recentPaths;
@@ -108,6 +116,7 @@ private:
// Return the value from the selected column, or an empty string if nothing selected
std::string getSelectedValue(const wxutil::TreeModel::Column& col);
+ bool getInsertAsGroup();
void handleSelectionChange();
void updateUsageInfo();
@@ -126,10 +135,10 @@ public:
* return the VFS path of the prefab selected by the user.
*
* @curPrefab: the name of the currently selected prefab the tree will browse to
- * Leave this empty to leave the treeview focus where it was when
- * the dialog was closed.
+ * Leave this empty to leave the treeview focus where it was when
+ * the dialog was closed.
*/
- static std::string ChoosePrefab(const std::string& curPrefab = "");
+ static Result ChoosePrefab(const std::string& curPrefab = "");
void onRadiantShutdown();
};
diff --git a/radiant/ui/prefdialog/PrefDialog.cpp b/radiant/ui/prefdialog/PrefDialog.cpp
index 2c64a62..61fae1b 100644
--- a/radiant/ui/prefdialog/PrefDialog.cpp
+++ b/radiant/ui/prefdialog/PrefDialog.cpp
@@ -9,110 +9,99 @@
#include <wx/sizer.h>
#include <wx/treebook.h>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/join.hpp>
-namespace ui
-{
+#include "settings/PreferenceSystem.h"
+#include "settings/PreferencePage.h"
-PrefDialog::PrefDialog() :
- _dialog(NULL),
- _notebook(NULL)
+namespace ui
{
- // There is no main application window by the time this constructor is called.
- createDialog(NULL);
-
- // Create the root element with the Notebook and Connector references
- _root = PrefPagePtr(new PrefPage("", _notebook));
-
- // Register this instance with GlobalRadiant() at once
- GlobalRadiant().signal_radiantShutdown().connect(
- sigc::mem_fun(*this, &PrefDialog::onRadiantShutdown)
- );
- GlobalRadiant().signal_radiantStarted().connect(
- sigc::mem_fun(*this, &PrefDialog::onRadiantStartup)
- );
-}
-void PrefDialog::createDialog(wxWindow* parent)
+PrefDialog::PrefDialog(wxWindow* parent) :
+ DialogBase(_("DarkRadiant Preferences"), parent),
+ _notebook(nullptr)
{
- wxutil::DialogBase* newDialog = new wxutil::DialogBase(_("DarkRadiant Preferences"), parent);
- newDialog->SetSizer(new wxBoxSizer(wxVERTICAL));
- newDialog->SetMinClientSize(wxSize(640, -1));
+ SetSizer(new wxBoxSizer(wxVERTICAL));
+ SetMinClientSize(wxSize(640, -1));
// 12-pixel spacer
- wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);
- newDialog->GetSizer()->Add(vbox, 1, wxEXPAND | wxALL, 12);
+ wxBoxSizer* mainVbox = new wxBoxSizer(wxVERTICAL);
+ GetSizer()->Add(mainVbox, 1, wxEXPAND | wxALL, 12);
- if (_notebook != NULL)
- {
- _notebook->Reparent(newDialog);
- }
- else
- {
- _notebook = new wxTreebook(newDialog, wxID_ANY);
- }
-
- vbox->Add(_notebook, 1, wxEXPAND);
- vbox->Add(newDialog->CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_RIGHT);
-
- // Prevent the tree control from shrinking too much
- _notebook->GetTreeCtrl()->SetMinClientSize(wxSize(200, -1));
-
- // Destroy the old dialog window and use the new one
- if (_dialog != NULL)
- {
- _dialog->Destroy();
- _dialog = NULL;
- }
+ mainVbox->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_RIGHT);
+
+ _notebook = new wxTreebook(this, wxID_ANY);
+
+ // Prevent the tree control from shrinking too much
+ _notebook->GetTreeCtrl()->SetMinClientSize(wxSize(200, -1));
- _dialog = newDialog;
-}
+ mainVbox->Prepend(_notebook, 1, wxEXPAND);
-PrefPagePtr PrefDialog::createOrFindPage(const std::string& path)
-{
- // Pass the call to the root page
- return _root->createOrFindPage(path);
+ // Create the page widgets
+ createPages();
}
-void PrefDialog::onRadiantStartup()
+void PrefDialog::createPages()
{
- // greebo: Unfortunate step needed at least in Windows. Creating a modal
- // dialog with a NULL parent (like we are doing) results in the dialog
- // using the currently active top level window as parent, which in our case
- // is the Splash window. The splash window is destroyed and this
- // dialog will be affected. So recreate the dialog window and reparent the
- // notebook to the new instance before the Splash screen goes the way of the dodo.
- createDialog(GlobalMainFrame().getWxTopLevelWindow());
-}
+ // Now create all pages
+ GetPreferenceSystem().foreachPage([&](settings::PreferencePage& page)
+ {
+ // Create a page responsible for this settings::PreferencePage
+ PrefPage* pageWidget = new PrefPage(_notebook, page);
-void PrefDialog::onRadiantShutdown()
-{
- rMessage() << "PrefDialog shutting down." << std::endl;
+ // Remember this page in our mapping
+ const std::string& pagePath = page.getPath();
- if (_dialog->IsShownOnScreen())
- {
- _dialog->Hide();
- }
+ _pages[pagePath] = pageWidget;
- // Destroy the window and let it go
- _dialog->Destroy();
- _dialog = NULL;
- _notebook = NULL;
+ std::vector<std::string> parts;
+ boost::algorithm::split(parts, pagePath, boost::algorithm::is_any_of("/"));
- InstancePtr().reset();
+ if (parts.size() > 1)
+ {
+ parts.pop_back();
+ std::string parentPath = boost::algorithm::join(parts, "/");
+
+ PageMap::const_iterator parent = _pages.find(parentPath);
+
+ if (parent != _pages.end())
+ {
+ // Find the index of the parent page to perform the insert
+ int pos = _notebook->FindPage(parent->second);
+ _notebook->InsertSubPage(pos, pageWidget, page.getName());
+ }
+ else
+ {
+ rError() << "Cannot insert page, unable to find parent path: " << parentPath << std::endl;
+ }
+ }
+ else
+ {
+ // Top-level page
+ // Append the panel as new page to the notebook
+ _notebook->AddPage(pageWidget, page.getName());
+ }
+ });
}
-void PrefDialog::doShowModal(const std::string& requestedPage)
+void PrefDialog::showModal(const std::string& requestedPage)
{
- // Trigger a resize of the treebook's TreeCtrl
- _notebook->ExpandNode(0, true);
-
- _dialog->FitToScreen(0.5f, 0.5f);
+ // Reset all values to the ones found in the registry
+ for (const PageMap::value_type& p : _pages)
+ {
+ p.second->resetValues();
+ }
- // Discard any changes we got earlier
- _root->foreachPage([&] (PrefPage& page)
+ // Trigger a resize of the treebook's TreeCtrl, do this by expanding all nodes
+ // (one would be enough, but we want to show the whole tree anyway)
+ for (std::size_t page = 0; page < _notebook->GetPageCount(); ++page)
{
- page.discardChanges();
- });
+ _notebook->ExpandNode(page, true);
+ }
+
+ FitToScreen(0.5f, 0.5f);
// Is there a specific page display request?
if (!requestedPage.empty())
@@ -120,13 +109,13 @@ void PrefDialog::doShowModal(const std::string& requestedPage)
showPage(requestedPage);
}
- if (_dialog->ShowModal() == wxID_OK)
+ if (ShowModal() == wxID_OK)
{
// Tell all pages to flush their buffer
- _root->foreachPage([&] (PrefPage& page)
+ for (const PageMap::value_type& p : _pages)
{
- page.saveChanges();
- });
+ p.second->saveChanges();
+ }
// greebo: Check if the mainframe module is already "existing". It might be
// uninitialised if this dialog is shown during DarkRadiant startup
@@ -135,67 +124,49 @@ void PrefDialog::doShowModal(const std::string& requestedPage)
GlobalMainFrame().updateAllWindows();
}
}
- else
- {
- // Discard all changes
- _root->foreachPage([&] (PrefPage& page)
- {
- page.discardChanges();
- });
- }
-}
-
-void PrefDialog::ShowDialog(const cmd::ArgumentList& args)
-{
- Instance().ShowModal();
}
-PrefDialogPtr& PrefDialog::InstancePtr()
+void PrefDialog::ShowPrefDialog(const cmd::ArgumentList& args)
{
- static PrefDialogPtr _instancePtr;
- return _instancePtr;
+ ShowDialog();
}
-PrefDialog& PrefDialog::Instance()
+void PrefDialog::showPage(const std::string& path)
{
- PrefDialogPtr& instancePtr = InstancePtr();
-
- if (instancePtr == NULL)
+ if (!_notebook)
{
- // Not yet instantiated, do it now
- instancePtr.reset(new PrefDialog);
+ rError() << "Can't show requested page, as the wxNotebook is null" << std::endl;
+ return;
}
- return *instancePtr;
-}
+ PageMap::const_iterator found = _pages.find(path);
-void PrefDialog::showPage(const std::string& path)
-{
- _root->foreachPage([&] (PrefPage& page)
+ if (found != _pages.end())
{
- // Check for a match
- if (page.getPath() == path)
- {
- // Find the page number
- int pagenum = _notebook->FindPage(page.getWidget());
+ // Find the page number
+ int pagenum = _notebook->FindPage(found->second);
- // make it active
- _notebook->SetSelection(pagenum);
- }
- });
+ // make it active
+ _notebook->SetSelection(pagenum);
+ }
}
-void PrefDialog::ShowModal(const std::string& path)
+void PrefDialog::ShowDialog(const std::string& path)
{
- if (!Instance()._dialog->IsShownOnScreen())
- {
- Instance().doShowModal(path);
- }
+ // greebo: Check if the mainframe module is already "existing". It might be
+ // uninitialised if this dialog is shown during DarkRadiant startup
+ wxWindow* parent = module::GlobalModuleRegistry().moduleExists(MODULE_MAINFRAME) ?
+ GlobalMainFrame().getWxTopLevelWindow() : nullptr;
+
+ PrefDialog* dialog = new PrefDialog(parent);
+
+ dialog->showModal(path);
+ dialog->Destroy();
}
void PrefDialog::ShowProjectSettings(const cmd::ArgumentList& args)
{
- ShowModal(_("Game"));
+ ShowDialog(_("Game"));
}
} // namespace ui
diff --git a/radiant/ui/prefdialog/PrefDialog.h b/radiant/ui/prefdialog/PrefDialog.h
index c1e6acb..7848ce2 100644
--- a/radiant/ui/prefdialog/PrefDialog.h
+++ b/radiant/ui/prefdialog/PrefDialog.h
@@ -1,63 +1,44 @@
#pragma once
+#include <map>
#include "iradiant.h"
#include "icommandsystem.h"
#include "PrefPage.h"
+#include "wxutil/dialog/DialogBase.h"
class wxTreebook;
-namespace wxutil { class DialogBase; }
-
namespace ui
{
-class PrefDialog;
-typedef std::shared_ptr<PrefDialog> PrefDialogPtr;
-
-class PrefDialog
+class PrefDialog :
+ public wxutil::DialogBase
{
private:
- // The actual dialog instance
- wxutil::DialogBase* _dialog;
-
wxTreebook* _notebook;
- // The root page
- PrefPagePtr _root;
+ // Each notebook page is created and maintained by a PrefPage class
+ // Map the page path wo its widget
+ typedef std::map<std::string, PrefPage*> PageMap;
+ PageMap _pages;
-public:
- PrefDialog();
-
- // Retrieve a reference to the static instance of this dialog
- static PrefDialog& Instance();
+ PrefDialog(wxWindow* parent);
+public:
/** greebo: Runs the modal dialog
*/
- static void ShowDialog(const cmd::ArgumentList& args);
+ static void ShowPrefDialog(const cmd::ArgumentList& args);
/** greebo: Makes sure that the dialog is visible.
* (does nothing if the dialog is already on screen)
*/
- static void ShowModal(const std::string& path = "");
+ static void ShowDialog(const std::string& path = "");
/** greebo: The command target to show the Game settings preferences.
*/
static void ShowProjectSettings(const cmd::ArgumentList& args);
- /** greebo: Looks up the page for the path and creates it
- * if necessary.
- */
- PrefPagePtr createOrFindPage(const std::string& path);
-
- // Reparent the preference dialog on startup
- void onRadiantStartup();
-
- /** greebo: A safe shutdown request that saves the window information
- * to the registry.
- */
- void onRadiantShutdown();
-
/** greebo: Displays the page with the specified path.
*
* @path: a string like "Settings/Patches"
@@ -65,12 +46,9 @@ public:
void showPage(const std::string& path);
private:
- void doShowModal(const std::string& requestedPage);
-
- // This is where the static shared_ptr of the singleton instance is held.
- static PrefDialogPtr& InstancePtr();
+ void showModal(const std::string& requestedPage);
- void createDialog(wxWindow* parent);
+ void createPages();
};
} // namespace ui
diff --git a/radiant/ui/prefdialog/PrefPage.cpp b/radiant/ui/prefdialog/PrefPage.cpp
index 80802ab..4422d38 100644
--- a/radiant/ui/prefdialog/PrefPage.cpp
+++ b/radiant/ui/prefdialog/PrefPage.cpp
@@ -1,106 +1,40 @@
#include "PrefPage.h"
#include "i18n.h"
-#include "itextstream.h"
-#include "registry/buffer.h"
-#include "registry/registry.h"
-#include "registry/Widgets.h"
-#include "wxutil/PathEntry.h"
-
-#include <iostream>
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string/trim.hpp>
-#include <boost/format.hpp>
-#include "modulesystem/ApplicationContextImpl.h"
-
-#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
-#include <wx/treebook.h>
-#include <wx/slider.h>
-#include <wx/spinctrl.h>
-#include <wx/textctrl.h>
-#include <wx/scrolwin.h>
-namespace ui
-{
+#include "settings/PreferenceItems.h"
+#include "PreferenceItem.h"
-namespace
+namespace ui
{
- typedef std::vector<std::string> StringVector;
-}
-PrefPage::PrefPage(const std::string& name,
- wxTreebook* notebook,
- const PrefPagePtr& parentPage) :
- _name(name),
- _notebook(notebook),
- _pageWidget(NULL),
- _titleLabel(NULL)
+PrefPage::PrefPage(wxWindow* parent, const settings::PreferencePage& settingsPage) :
+ wxScrolledWindow(parent, wxID_ANY),
+ _settingsPage(settingsPage)
{
- if (parentPage && !parentPage->getPath().empty())
- {
- _path = parentPage->getPath() + "/" + _name;
- }
- else
- {
- _path = _name;
- }
-
- if (!_name.empty())
- {
- // Create the overall panel
- _pageWidget = new wxScrolledWindow(_notebook, wxID_ANY);
- _pageWidget->SetScrollRate(0, 3);
-
- _pageWidget->SetSizer(new wxBoxSizer(wxVERTICAL));
-
- // 12 pixel border
- wxBoxSizer* overallVBox = new wxBoxSizer(wxVERTICAL);
- _pageWidget->GetSizer()->Add(overallVBox, 1, wxEXPAND | wxALL, 12);
+ // Create the overall panel
+ SetScrollRate(0, 3);
+ SetSizer(new wxBoxSizer(wxVERTICAL));
- // Create the label
- _titleLabel = new wxStaticText(_pageWidget, wxID_ANY,
- (boost::format("%s Settings") % _name).str()
- );
- _titleLabel->SetFont(_titleLabel->GetFont().Bold());
- overallVBox->Add(_titleLabel, 0, wxBOTTOM, 12);
+ // 12 pixel border
+ wxBoxSizer* overallVBox = new wxBoxSizer(wxVERTICAL);
+ GetSizer()->Add(overallVBox, 1, wxEXPAND | wxALL, 12);
- _table = new wxFlexGridSizer(1, 2, 6, 12);
- overallVBox->Add(_table, 1, wxEXPAND | wxLEFT, 6); // another 12 pixels to the left
+ // Create the label
+ wxStaticText* titleLabel = new wxStaticText(this, wxID_ANY, _settingsPage.getTitle());
+ titleLabel->SetFont(titleLabel->GetFont().Bold());
+ overallVBox->Add(titleLabel, 0, wxBOTTOM, 12);
- if (parentPage && !parentPage->getName().empty())
- {
- // Find the index of the parent page to perform the insert
- int pos = _notebook->FindPage(parentPage->getWidget());
- _notebook->InsertSubPage(pos, _pageWidget, name);
- }
- else if (!_name.empty())
- {
- // Append the panel as new page to the notebook
- _notebook->AddPage(_pageWidget, name);
- }
- }
-}
+ _table = new wxFlexGridSizer(1, 2, 6, 12);
+ overallVBox->Add(_table, 1, wxEXPAND | wxLEFT, 6); // another 12 pixels to the left
-void PrefPage::setTitle(const std::string& title)
-{
- if (_titleLabel != NULL)
+ settingsPage.foreachItem([&](const settings::PreferenceItemBasePtr& item)
{
- _titleLabel->SetLabelText(title);
- }
-}
-
-std::string PrefPage::getPath() const
-{
- return _path;
-}
-
-std::string PrefPage::getName() const
-{
- return _name;
+ createItemWidgets(item);
+ });
}
void PrefPage::saveChanges()
@@ -108,254 +42,80 @@ void PrefPage::saveChanges()
_registryBuffer.commitChanges();
}
-void PrefPage::discardChanges()
+void PrefPage::resetValues()
{
_registryBuffer.clear();
_resetValuesSignal();
}
-wxWindow* PrefPage::getWidget()
-{
- return _pageWidget;
-}
-
-void PrefPage::foreachPage(const std::function<void(PrefPage&)>& functor)
+void PrefPage::appendNamedWidget(const std::string& name, wxWindow* widget, bool useFullWidth)
{
- std::for_each(_children.begin(), _children.end(), [&] (const PrefPagePtr& page)
+ if (_table->GetItemCount() > 0)
{
- // Visit this instance
- functor(*page);
-
- // Pass the visitor recursively
- page->foreachPage(functor);
- });
-}
-
-void PrefPage::appendCheckBox(const std::string& name,
- const std::string& flag,
- const std::string& registryKey)
-{
- // Create a new checkbox with the given caption and display it
- wxCheckBox* check = new wxCheckBox(_pageWidget, wxID_ANY, flag);
-
- // Connect the registry key to this toggle button
- registry::bindWidgetToBufferedKey(check, registryKey, _registryBuffer, _resetValuesSignal);
-
- appendNamedWidget(name, check);
-}
-
-void PrefPage::appendSlider(const std::string& name, const std::string& registryKey, bool drawValue,
- double value, double lower, double upper, double step_increment, double page_increment, double page_size)
-{
- // Since sliders are int only, we need to factor the values to support floats
- int factor = static_cast<int>(1 / step_increment);
-
- wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
-
- wxSlider* slider = new wxSlider(_pageWidget, wxID_ANY, value * factor, lower * factor, upper * factor);
- slider->SetPageSize(page_increment * factor);
-
- // Add a text widget displaying the value
- wxStaticText* valueText = new wxStaticText(_pageWidget, wxID_ANY, "");
- slider->Bind(wxEVT_SCROLL_CHANGED, [=] (wxScrollEvent& ev)
- {
- valueText->SetLabelText(string::to_string(slider->GetValue()));
- ev.Skip();
- });
- slider->Bind(wxEVT_SCROLL_THUMBTRACK, [=] (wxScrollEvent& ev)
- {
- valueText->SetLabelText(string::to_string(slider->GetValue()));
- ev.Skip();
- });
- valueText->SetLabelText(string::to_string(value));
-
- hbox->Add(valueText, 0, wxALIGN_CENTER_VERTICAL);
- hbox->Add(slider, 1, wxEXPAND | wxLEFT, 6);
-
- // Connect the registry key to this adjustment
- registry::bindWidgetToBufferedKey(slider, registryKey, _registryBuffer, _resetValuesSignal, factor);
-
- appendNamedSizer(name, hbox);
-}
-
-void PrefPage::appendCombo(const std::string& name,
- const std::string& registryKey,
- const ComboBoxValueList& valueList,
- bool storeValueNotIndex)
-{
- wxChoice* choice = new wxChoice(_pageWidget, wxID_ANY);
-
- // Add all the string values to the combo box
- for (ComboBoxValueList::const_iterator i = valueList.begin();
- i != valueList.end();
- ++i)
- {
- choice->Append(*i);
- }
-
- registry::bindWidgetToBufferedKey(choice, registryKey, _registryBuffer, _resetValuesSignal, storeValueNotIndex);
-
- // Add the widget to the dialog row
- appendNamedWidget(name, choice, false);
-}
-
-void PrefPage::appendEntry(const std::string& name, const std::string& registryKey)
-{
- wxTextCtrl* entry = new wxTextCtrl(_pageWidget, wxID_ANY);
-
- int minChars = static_cast<int>(std::max(GlobalRegistry().get(registryKey).size(), std::size_t(30)));
- entry->SetMinClientSize(wxSize(entry->GetCharWidth() * minChars, -1));
-
- // Connect the registry key to the newly created input field
- registry::bindWidgetToBufferedKey(entry, registryKey, _registryBuffer, _resetValuesSignal);
-
- appendNamedWidget(name, entry);
-}
-
-void PrefPage::appendLabel(const std::string& caption)
-{
- wxStaticText* label = new wxStaticText(_pageWidget, wxID_ANY, "");
- label->SetLabelMarkup(caption);
-
- appendNamedWidget("", label);
-}
-
-void PrefPage::appendPathEntry(const std::string& name, const std::string& registryKey, bool browseDirectories)
-{
- wxutil::PathEntry* entry = new wxutil::PathEntry(_pageWidget, browseDirectories);
-
- // Connect the registry key to the newly created input field
- registry::bindWidgetToBufferedKey(entry->getEntryWidget(),
- registryKey, _registryBuffer, _resetValuesSignal);
-
- int minChars = static_cast<int>(std::max(GlobalRegistry().get(registryKey).size(), std::size_t(30)));
-
- entry->getEntryWidget()->SetMinClientSize(
- wxSize(entry->getEntryWidget()->GetCharWidth() * minChars, -1));
-
- // Initialize entry
- entry->setValue(registry::getValue<std::string>(registryKey));
+ // Add another row
+ _table->SetRows(_table->GetRows() + 1);
+ }
- appendNamedWidget(name, entry);
+ _table->Add(new wxStaticText(this, wxID_ANY, name), 0, wxALIGN_CENTRE_VERTICAL);
+ _table->Add(widget, useFullWidth ? 1 : 0, wxEXPAND);
}
-void PrefPage::appendSpinner(const std::string& name, const std::string& registryKey,
- double lower, double upper, int fraction)
+void PrefPage::createItemWidgets(const settings::PreferenceItemBasePtr& item)
{
- // Load the initial value (maybe unnecessary, as the value is loaded upon dialog show)
- float value = registry::getValue<float>(registryKey);
-
- double step = 1.0 / static_cast<double>(fraction);
- unsigned int digits = 0;
+ // Construct a generic item and pass the common values
+ PreferenceItem widget(this, item->getRegistryKey(), _registryBuffer, _resetValuesSignal);
+
+ // Switch on the item type
+ if (std::dynamic_pointer_cast<settings::PreferenceLabel>(item))
+ {
+ wxWindow* label = widget.createLabel(item->getLabel());
- for (;fraction > 1; fraction /= 10)
+ appendNamedWidget("", label);
+ }
+ else if (std::dynamic_pointer_cast<settings::PreferenceEntry>(item))
{
- ++digits;
+ appendNamedWidget(item->getLabel(), widget.createEntry());
}
-
- if (digits == 0)
+ else if (std::dynamic_pointer_cast<settings::PreferenceCheckbox>(item))
{
- wxSpinCtrl* spinner = new wxSpinCtrl(_pageWidget, wxID_ANY);
-
- spinner->SetRange(static_cast<int>(lower), static_cast<int>(upper));
- spinner->SetValue(static_cast<int>(value));
+ wxWindow* checkbox = widget.createCheckbox(item->getLabel());
- spinner->SetMinClientSize(wxSize(64, -1));
-
- // Connect the registry key to the newly created input field
- registry::bindWidgetToBufferedKey(spinner, registryKey, _registryBuffer, _resetValuesSignal);
-
- appendNamedWidget(name, spinner);
+ appendNamedWidget("", checkbox);
}
- else
+ else if (std::dynamic_pointer_cast<settings::PreferenceCombobox>(item))
{
- wxSpinCtrlDouble* spinner = new wxSpinCtrlDouble(_pageWidget, wxID_ANY);
-
- spinner->SetRange(lower, upper);
- spinner->SetValue(value);
- spinner->SetIncrement(step);
+ std::shared_ptr<settings::PreferenceCombobox> info = std::static_pointer_cast<settings::PreferenceCombobox>(item);
- spinner->SetMinClientSize(wxSize(64, -1));
+ wxWindow* combobox = widget.createCombobox(info->getValues(), info->storeValueNotIndex());
- // Connect the registry key to the newly created input field
- registry::bindWidgetToBufferedKey(spinner, registryKey, _registryBuffer, _resetValuesSignal);
-
- appendNamedWidget(name, spinner);
+ appendNamedWidget(item->getLabel(), combobox, false);
}
-}
-
-PrefPagePtr PrefPage::createOrFindPage(const std::string& path)
-{
- // Split the path into parts
- StringVector parts;
- boost::algorithm::split(parts, path, boost::algorithm::is_any_of("/"));
-
- if (parts.empty())
+ else if (std::dynamic_pointer_cast<settings::PreferencePathEntry>(item))
{
- rConsole() << "Warning: Could not resolve preference path: " << path << std::endl;
- return PrefPagePtr();
- }
+ std::shared_ptr<settings::PreferencePathEntry> info = std::static_pointer_cast<settings::PreferencePathEntry>(item);
- PrefPagePtr child;
+ wxWindow* pathEntry = widget.createPathEntry(info->browseDirectories());
- // Try to lookup the page in the child list
- for (std::size_t i = 0; i < _children.size(); ++i)
- {
- if (_children[i]->getName() == parts[0])
- {
- child = _children[i];
- break;
- }
+ appendNamedWidget(item->getLabel(), pathEntry);
}
-
- if (child == NULL)
+ else if (std::dynamic_pointer_cast<settings::PreferenceSpinner>(item))
{
- // No child found, create a new page and add it to the list
- child = PrefPagePtr(new PrefPage(parts[0], _notebook, shared_from_this()));
- _children.push_back(child);
- }
+ std::shared_ptr<settings::PreferenceSpinner> info = std::static_pointer_cast<settings::PreferenceSpinner>(item);
- // We now have a child with this name, do we have a leaf?
- if (parts.size() > 1) {
- // We have still more parts, split off the first part
- std::string subPath("");
- for (std::size_t i = 1; i < parts.size(); ++i)
- {
- subPath += (subPath.empty()) ? "" : "/";
- subPath += parts[i];
- }
- // Pass the call to the child
- return child->createOrFindPage(subPath);
- }
- else {
- // We have found a leaf, return the child page
- return child;
- }
-}
+ wxWindow* spinner = widget.createSpinner(info->getLower(), info->getUpper(), info->getFraction());
-void PrefPage::appendNamedWidget(const std::string& name, wxWindow* widget, bool useFullWidth)
-{
- if (_table->GetItemCount() > 0)
- {
- // Add another row
- _table->SetRows(_table->GetRows() + 1);
+ appendNamedWidget(item->getLabel(), spinner);
}
+ else if (std::dynamic_pointer_cast<settings::PreferenceSlider>(item))
+ {
+ std::shared_ptr<settings::PreferenceSlider> info = std::static_pointer_cast<settings::PreferenceSlider>(item);
- _table->Add(new wxStaticText(_pageWidget, wxID_ANY, name), 0, wxALIGN_CENTRE_VERTICAL);
- _table->Add(widget, useFullWidth ? 1 : 0, wxEXPAND);
-}
+ wxWindow* slider = widget.createSlider(info->getLower(), info->getUpper(),
+ info->getStepIncrement(), info->getPageIncrement());
-void PrefPage::appendNamedSizer(const std::string& name, wxSizer* sizer, bool useFullWidth)
-{
- if (_table->GetItemCount() > 0)
- {
- // Add another row
- _table->SetRows(_table->GetRows() + 1);
+ appendNamedWidget(item->getLabel(), slider);
}
-
- _table->Add(new wxStaticText(_pageWidget, wxID_ANY, name), 0, wxALIGN_CENTRE_VERTICAL);
- _table->Add(sizer, useFullWidth ? 1 : 0, wxEXPAND);
}
} // namespace ui
diff --git a/radiant/ui/prefdialog/PrefPage.h b/radiant/ui/prefdialog/PrefPage.h
index faa44ac..7a05ba1 100644
--- a/radiant/ui/prefdialog/PrefPage.h
+++ b/radiant/ui/prefdialog/PrefPage.h
@@ -1,26 +1,26 @@
#pragma once
-#include "registry/buffer.h"
-#include <wx/panel.h>
+#include <wx/scrolwin.h>
-#include "ipreferencesystem.h"
+#include "registry/buffer.h"
+#include "settings/PreferencePage.h"
-class wxTreebook;
class wxFlexGridSizer;
-class wxStaticText;
-class wxSizer;
-class wxScrolledWindow;
-namespace ui {
-
-class PrefPage;
-typedef std::shared_ptr<PrefPage> PrefPagePtr;
+namespace ui
+{
+/**
+ * A preference page as inserted into the PrefDialog's treebook control.
+ * Each PrefPage renders the items found in the assigned settings::PreferencePage.
+ */
class PrefPage :
- public PreferencesPage,
- public std::enable_shared_from_this<PrefPage>
+ public wxScrolledWindow
{
private:
+ // The settings page we're representing
+ const settings::PreferencePage& _settingsPage;
+
// We're holding back any registry write operations until the user clicks OK
registry::Buffer _registryBuffer;
@@ -31,105 +31,20 @@ private:
// The table this page is adding the widgets to
wxFlexGridSizer* _table;
- // The list of child pages
- std::vector<PrefPagePtr> _children;
-
- // The name (caption) of this page
- std::string _name;
-
- // The full path of this object
- std::string _path;
-
- // The notebook this page is packed into
- wxTreebook* _notebook;
-
- // The actual page that gets attached to the notebook
- wxScrolledWindow* _pageWidget;
-
- wxStaticText* _titleLabel;
-
public:
- /** greebo: Constructor
- *
- * @name: The display caption of this prefpage
- * @parentPath: the path to the parent of this page
- * @notebook: The notebook widget this page is child of.
- */
- PrefPage(const std::string& name,
- wxTreebook* notebook,
- const PrefPagePtr& parentPage = PrefPagePtr());
-
- /** greebo: Sets the title caption that is displayed on the right.
- * Overrides the default title that is generated
- * on construction (the one with the " Settings" postfix).
- */
- void setTitle(const std::string& title);
-
- /** greebo: Returns the full path to this PrefPage
- */
- std::string getPath() const;
+ PrefPage(wxWindow* parent, const settings::PreferencePage& settingsPage);
- /** greebo: Returns the name (caption) of this Page (e.g. "Settings")
- */
- std::string getName() const;
-
- /**
- * Commit all pending registry write operations.
- */
+ // Commit all pending registry write operations.
void saveChanges();
- /**
- * Discard all pending registry write operations.
- */
- void discardChanges();
-
- /** greebo: Returns the widget that can be used to determine
- * the notebook page number.
- */
- wxWindow* getWidget();
-
- void foreachPage(const std::function<void(PrefPage&)>& functor);
-
- // Appends a simple static label
- void appendLabel(const std::string& caption);
-
- /* greebo: This adds a checkbox and connects it to an XMLRegistry key.
- * @returns: the pointer to the created GtkWidget */
- void appendCheckBox(const std::string& name, const std::string& flag, const std::string& registryKey);
-
- /* greebo: This adds a horizontal slider to the internally referenced VBox and connects
- * it to the given registryKey. */
- void appendSlider(const std::string& name, const std::string& registryKey, bool drawValue,
- double value, double lower, double upper, double step_increment, double page_increment, double page_size) ;
-
- void appendCombo(const std::string& name,
- const std::string& registryKey,
- const ComboBoxValueList& valueList,
- bool storeValueNotIndex = false);
-
- /* greebo: Appends an entry field with <name> as caption which is connected to the given registryKey
- */
- void appendEntry(const std::string& name, const std::string& registryKey);
-
- // greebo: Adds a PathEntry to choose files or directories (depending on the given boolean)
- void appendPathEntry(const std::string& name, const std::string& registryKey, bool browseDirectories);
-
- /* greebo: Appends an entry field with spinner buttons which retrieves its value from the given
- * RegistryKey. The lower and upper values have to be passed as well.
- */
- void appendSpinner(const std::string& name, const std::string& registryKey,
- double lower, double upper, int fraction);
-
- /** greebo: Performs a recursive lookup of the given path
- * and creates any items that do not exist.
- *
- * @returns: the shared_ptr to the PrefPage, can be empty on error.
- */
- PrefPagePtr createOrFindPage(const std::string& path);
+ // Discard all pending registry write operations.
+ void resetValues();
private:
void appendNamedWidget(const std::string& name, wxWindow* widget, bool useFullWidth = true);
- void appendNamedSizer(const std::string& name, wxSizer* sizer, bool useFullWidth = true);
+
+ void createItemWidgets(const settings::PreferenceItemBasePtr& item);
};
+typedef std::shared_ptr<PrefPage> PrefPagePtr;
} // namespace ui
diff --git a/radiant/ui/prefdialog/PreferenceItem.cpp b/radiant/ui/prefdialog/PreferenceItem.cpp
new file mode 100644
index 0000000..fe931fe
--- /dev/null
+++ b/radiant/ui/prefdialog/PreferenceItem.cpp
@@ -0,0 +1,164 @@
+#include "PreferenceItem.h"
+
+#include <wx/stattext.h>
+#include <wx/checkbox.h>
+#include <wx/slider.h>
+#include <wx/sizer.h>
+#include <wx/combobox.h>
+#include <wx/choice.h>
+#include <wx/panel.h>
+#include <wx/scrolwin.h>
+#include "registry/Widgets.h"
+#include "wxutil/PathEntry.h"
+
+namespace ui
+{
+
+wxWindow* PreferenceItem::createLabel(const std::string& label)
+{
+ wxStaticText* labelWidget = new wxStaticText(_parent, wxID_ANY, "");
+ labelWidget->SetLabelMarkup(label);
+
+ return labelWidget;
+}
+
+wxWindow* PreferenceItem::createEntry()
+{
+ wxTextCtrl* entryWidget = new wxTextCtrl(_parent, wxID_ANY);
+
+ int minChars = static_cast<int>(std::max(_buffer.get(_registryKey).size(), std::size_t(30)));
+ entryWidget->SetMinClientSize(wxSize(entryWidget->GetCharWidth() * minChars, -1));
+
+ // Connect the registry key to the newly created input field
+ registry::bindWidgetToBufferedKey(entryWidget, _registryKey, _buffer, _resetSignal);
+
+ return entryWidget;
+}
+
+wxWindow* PreferenceItem::createCheckbox(const std::string& label)
+{
+ wxCheckBox* checkbox = new wxCheckBox(_parent, wxID_ANY, label);
+
+ // Connect the registry key to this checkbox
+ registry::bindWidgetToBufferedKey(checkbox, _registryKey, _buffer, _resetSignal);
+
+ return checkbox;
+}
+
+wxWindow* PreferenceItem::createCombobox(const ComboBoxValueList& values, bool storeValueNotIndex)
+{
+ wxChoice* choice = new wxChoice(_parent, wxID_ANY);
+
+ // Add all the string values to the combo box
+ for (const std::string& value : values)
+ {
+ choice->Append(value);
+ }
+
+ // Connect the registry key to this combo
+ registry::bindWidgetToBufferedKey(choice, _registryKey, _buffer, _resetSignal, storeValueNotIndex);
+
+ return choice;
+}
+
+wxWindow* PreferenceItem::createPathEntry(bool browseDirectories)
+{
+ wxutil::PathEntry* entry = new wxutil::PathEntry(_parent, browseDirectories);
+
+ // Connect the registry key to the newly created input field
+ registry::bindWidgetToBufferedKey(entry->getEntryWidget(), _registryKey, _buffer, _resetSignal);
+
+ int minChars = static_cast<int>(std::max(GlobalRegistry().get(_registryKey).size(), std::size_t(30)));
+
+ entry->getEntryWidget()->SetMinClientSize(
+ wxSize(entry->getEntryWidget()->GetCharWidth() * minChars, -1));
+
+ // Initialize entry
+ entry->setValue(registry::getValue<std::string>(_registryKey));
+
+ return entry;
+}
+
+wxWindow* PreferenceItem::createSpinner(double lower, double upper, int fractionInt)
+{
+ double fraction = static_cast<double>(fractionInt);
+ double step = 1.0 / fraction;
+ unsigned int digits = 0;
+
+ for (; fraction > 1; fraction /= 10)
+ {
+ ++digits;
+ }
+
+ if (digits == 0)
+ {
+ wxSpinCtrl* spinner = new wxSpinCtrl(_parent, wxID_ANY);
+
+ spinner->SetRange(static_cast<int>(lower), static_cast<int>(upper));
+ spinner->SetMinClientSize(wxSize(64, -1));
+
+ // Connect the registry key to the newly created spinbutton
+ registry::bindWidgetToBufferedKey(spinner, _registryKey, _buffer, _resetSignal);
+
+ return spinner;
+ }
+ else
+ {
+ wxSpinCtrlDouble* spinner = new wxSpinCtrlDouble(_parent, wxID_ANY);
+
+ spinner->SetRange(lower, upper);
+ spinner->SetIncrement(step);
+ spinner->SetMinClientSize(wxSize(64, -1));
+
+ // Connect the registry key to the newly created spinbutton
+ registry::bindWidgetToBufferedKey(spinner, _registryKey, _buffer, _resetSignal);
+
+ return spinner;
+ }
+}
+
+wxWindow* PreferenceItem::createSlider(double lower, double upper, double stepIncrement, double pageIncrement)
+{
+ // Since sliders are int only, we need to factor the values to support floats
+ int factor = static_cast<int>(1 / stepIncrement);
+
+ wxPanel* panel = new wxPanel(_parent, wxID_ANY);
+
+ wxBoxSizer* hbox = new wxBoxSizer(wxHORIZONTAL);
+ panel->SetSizer(hbox);
+
+ // Get the current value from the registry
+ double value = registry::getValue<float>(_registryKey) * factor;
+
+ wxSlider* slider = new wxSlider(panel, wxID_ANY, value * factor, lower * factor, upper * factor);
+ slider->SetPageSize(pageIncrement * factor);
+
+ // Add a text widget displaying the value
+ wxStaticText* valueLabel = new wxStaticText(panel, wxID_ANY, "");
+ slider->Bind(wxEVT_SCROLL_CHANGED, [=](wxScrollEvent& ev)
+ {
+ valueLabel->SetLabelText(string::to_string(slider->GetValue()));
+ ev.Skip();
+ });
+
+ slider->Bind(wxEVT_SCROLL_THUMBTRACK, [=](wxScrollEvent& ev)
+ {
+ valueLabel->SetLabelText(string::to_string(slider->GetValue()));
+ ev.Skip();
+ });
+
+ valueLabel->SetLabelText(string::to_string(value));
+
+ hbox->Add(valueLabel, 0, wxALIGN_CENTER_VERTICAL);
+ hbox->Add(slider, 1, wxEXPAND | wxLEFT, 6);
+
+ // Connect the registry key to this slider
+ registry::bindWidgetToBufferedKey(slider, _registryKey, _buffer, _resetSignal, factor);
+
+ // Update the value text now, the wxSlider::SetValue() doesn't trigger the changed signal
+ valueLabel->SetLabelText(string::to_string(slider->GetValue()));
+
+ return panel;
+}
+
+} // namespace
diff --git a/radiant/ui/prefdialog/PreferenceItem.h b/radiant/ui/prefdialog/PreferenceItem.h
new file mode 100644
index 0000000..ba56a98
--- /dev/null
+++ b/radiant/ui/prefdialog/PreferenceItem.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <string>
+#include <sigc++/signal.h>
+
+#include "ipreferencesystem.h"
+#include "registry/buffer.h"
+
+class wxWindow;
+
+namespace ui
+{
+
+// Helper class creating and setting up various types of preference UI elements
+class PreferenceItem
+{
+protected:
+ wxWindow* _parent;
+ std::string _registryKey;
+ registry::Buffer& _buffer;
+ sigc::signal<void>& _resetSignal;
+
+public:
+ PreferenceItem(wxWindow* parent, const std::string& registryKey,
+ registry::Buffer& buffer, sigc::signal<void>& resetSignal) :
+ _parent(parent),
+ _registryKey(registryKey),
+ _buffer(buffer),
+ _resetSignal(resetSignal)
+ {}
+
+ wxWindow* createLabel(const std::string& label);
+
+ wxWindow* createEntry();
+
+ wxWindow* createCheckbox(const std::string& label);
+
+ wxWindow* createCombobox(const ComboBoxValueList& values, bool storeValueNotIndex);
+
+ wxWindow* createPathEntry(bool browseDirectories);
+
+ wxWindow* createSpinner(double lower, double upper, int fraction);
+
+ wxWindow* createSlider(double lower, double upper, double stepIncrement, double pageIncrement);
+};
+
+} // namespace
diff --git a/radiant/ui/texturebrowser/TextureBrowser.cpp b/radiant/ui/texturebrowser/TextureBrowser.cpp
index 3d240ea..baf3398 100644
--- a/radiant/ui/texturebrowser/TextureBrowser.cpp
+++ b/radiant/ui/texturebrowser/TextureBrowser.cpp
@@ -116,35 +116,35 @@ public:
if ((position.y() - size.y() - FONT_HEIGHT() < _owner.getOriginY()) &&
(position.y() > _owner.getOriginY() - _owner.getViewportHeight()))
{
- drawBorder(*material, position, size);
- drawTextureQuad(texture->getGLTexNum(), position, size);
- drawTextureName(*material, position, size);
+ drawBorder();
+ drawTextureQuad(texture->getGLTexNum());
+ drawTextureName();
}
}
private:
- void drawBorder(const Material& material, const Vector2i& pos, const Vector2i& size)
+ void drawBorder()
{
// borders rules:
// if it's the current texture, draw a thick red line, else:
// shaders have a white border, simple textures don't
// if !texture_showinuse: (some textures displayed may not be in use)
// draw an additional square around with 0.5 1 0.5 color
- if (shader_equal(_owner.getSelectedShader(), material.getName()))
+ if (shader_equal(_owner.getSelectedShader(), material->getName()))
{
glLineWidth(3);
glColor3f(1, 0, 0);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_LOOP);
- glVertex2i(pos.x() - TILE_BORDER,
- pos.y() - FONT_HEIGHT() + TILE_BORDER);
- glVertex2i(pos.x() - TILE_BORDER,
- pos.y() - FONT_HEIGHT() - size.y() - TILE_BORDER);
- glVertex2i(pos.x() + TILE_BORDER + size.x(),
- pos.y() - FONT_HEIGHT() - size.y() - TILE_BORDER);
- glVertex2i(pos.x() + TILE_BORDER + size.x(),
- pos.y() - FONT_HEIGHT() + TILE_BORDER);
+ glVertex2i(position.x() - TILE_BORDER,
+ position.y() - FONT_HEIGHT() + TILE_BORDER);
+ glVertex2i(position.x() - TILE_BORDER,
+ position.y() - FONT_HEIGHT() - size.y() - TILE_BORDER);
+ glVertex2i(position.x() + TILE_BORDER + size.x(),
+ position.y() - FONT_HEIGHT() - size.y() - TILE_BORDER);
+ glVertex2i(position.x() + TILE_BORDER + size.x(),
+ position.y() - FONT_HEIGHT() + TILE_BORDER);
glEnd();
glEnable(GL_TEXTURE_2D);
@@ -155,45 +155,45 @@ private:
glLineWidth(1);
// material border:
- if (!material.IsDefault())
+ if (!material->IsDefault())
{
glColor3f(1, 1, 1);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_LOOP);
- glVertex2i(pos.x() - 1,
- pos.y() + 1 - FONT_HEIGHT());
- glVertex2i(pos.x() - 1,
- pos.y() - size.y() - 1 - FONT_HEIGHT());
- glVertex2i(pos.x() + 1 + size.x(),
- pos.y() - size.y() - 1 - FONT_HEIGHT());
- glVertex2i(pos.x() + 1 + size.x(),
- pos.y() + 1 - FONT_HEIGHT());
+ glVertex2i(position.x() - 1,
+ position.y() + 1 - FONT_HEIGHT());
+ glVertex2i(position.x() - 1,
+ position.y() - size.y() - 1 - FONT_HEIGHT());
+ glVertex2i(position.x() + 1 + size.x(),
+ position.y() - size.y() - 1 - FONT_HEIGHT());
+ glVertex2i(position.x() + 1 + size.x(),
+ position.y() + 1 - FONT_HEIGHT());
glEnd();
glEnable(GL_TEXTURE_2D);
}
// highlight in-use textures
- if (!_owner._hideUnused && material.IsInUse())
+ if (!_owner._hideUnused && material->IsInUse())
{
glColor3f(0.5f, 1, 0.5f);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_LOOP);
- glVertex2i(pos.x() - 3,
- pos.y() + 3 - FONT_HEIGHT());
- glVertex2i(pos.x() - 3,
- pos.y() - size.y() - 3 - FONT_HEIGHT());
- glVertex2i(pos.x() + 3 + size.x(),
- pos.y() - size.y() - 3 - FONT_HEIGHT());
- glVertex2i(pos.x() + 3 + size.x(),
- pos.y() + 3 - FONT_HEIGHT());
+ glVertex2i(position.x() - 3,
+ position.y() + 3 - FONT_HEIGHT());
+ glVertex2i(position.x() - 3,
+ position.y() - size.y() - 3 - FONT_HEIGHT());
+ glVertex2i(position.x() + 3 + size.x(),
+ position.y() - size.y() - 3 - FONT_HEIGHT());
+ glVertex2i(position.x() + 3 + size.x(),
+ position.y() + 3 - FONT_HEIGHT());
glEnd();
glEnable(GL_TEXTURE_2D);
}
}
}
- void drawTextureQuad(GLuint num, const Vector2i& pos, const Vector2i& size)
+ void drawTextureQuad(GLuint num)
{
glBindTexture(GL_TEXTURE_2D, num);
GlobalOpenGL().assertNoErrors();
@@ -201,26 +201,26 @@ private:
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
- glVertex2i(pos.x(), pos.y() - FONT_HEIGHT());
+ glVertex2i(position.x(), position.y() - FONT_HEIGHT());
glTexCoord2i(1, 0);
- glVertex2i(pos.x() + size.x(), pos.y() - FONT_HEIGHT());
+ glVertex2i(position.x() + size.x(), position.y() - FONT_HEIGHT());
glTexCoord2i(1, 1);
- glVertex2i(pos.x() + size.x(), pos.y() - FONT_HEIGHT() - size.y());
+ glVertex2i(position.x() + size.x(), position.y() - FONT_HEIGHT() - size.y());
glTexCoord2i(0, 1);
- glVertex2i(pos.x(), pos.y() - FONT_HEIGHT() - size.y());
+ glVertex2i(position.x(), position.y() - FONT_HEIGHT() - size.y());
glEnd();
}
- void drawTextureName(const Material& material, const Vector2i& pos, const Vector2i& size)
+ void drawTextureName()
{
glDisable(GL_TEXTURE_2D);
glColor3f(1, 1, 1);
const static int FONT_OFFSET = 6;
- glRasterPos2i(pos.x(), pos.y() - FONT_HEIGHT() + FONT_OFFSET);
+ glRasterPos2i(position.x(), position.y() - FONT_HEIGHT() + FONT_OFFSET);
// don't draw the directory name
- std::string name = material.getName();
+ std::string name = material->getName();
name = name.substr(name.rfind("/") + 1);
// Ellipsize the name if it's too long
@@ -819,7 +819,7 @@ void TextureBrowser::openContextMenu() {
}
}
- _shaderLabel->SetText(shaderText);
+ _shaderLabel->SetItemLabel(shaderText);
_popupMenu->show(_wxGLWidget);
}
diff --git a/radiant/ui/texturebrowser/TextureBrowserManager.cpp b/radiant/ui/texturebrowser/TextureBrowserManager.cpp
index 0cdb303..6628b3d 100644
--- a/radiant/ui/texturebrowser/TextureBrowserManager.cpp
+++ b/radiant/ui/texturebrowser/TextureBrowserManager.cpp
@@ -58,14 +58,14 @@ void TextureBrowserManager::updateAllWindows()
void TextureBrowserManager::registerPreferencePage()
{
// Add a page to the given group
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Texture Browser"));
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Texture Browser"));
- page->appendEntry(_("Uniform texture thumbnail size (pixels)"), RKEY_TEXTURE_UNIFORM_SIZE);
- page->appendCheckBox("", _("Texture scrollbar"), RKEY_TEXTURE_SHOW_SCROLLBAR);
- page->appendEntry(_("Mousewheel Increment"), RKEY_TEXTURE_MOUSE_WHEEL_INCR);
- page->appendSpinner(_("Max shadername length"), RKEY_TEXTURE_MAX_NAME_LENGTH, 4, 100, 1);
+ page.appendEntry(_("Uniform texture thumbnail size (pixels)"), RKEY_TEXTURE_UNIFORM_SIZE);
+ page.appendCheckBox(_("Texture scrollbar"), RKEY_TEXTURE_SHOW_SCROLLBAR);
+ page.appendEntry(_("Mousewheel Increment"), RKEY_TEXTURE_MOUSE_WHEEL_INCR);
+ page.appendSpinner(_("Max shadername length"), RKEY_TEXTURE_MAX_NAME_LENGTH, 4, 100, 1);
- page->appendCheckBox("", _("Show Texture Filter"), RKEY_TEXTURE_SHOW_FILTER);
+ page.appendCheckBox(_("Show Texture Filter"), RKEY_TEXTURE_SHOW_FILTER);
}
// Static command target
diff --git a/radiant/xyview/GlobalXYWnd.cpp b/radiant/xyview/GlobalXYWnd.cpp
index 7e472e8..74239fa 100644
--- a/radiant/xyview/GlobalXYWnd.cpp
+++ b/radiant/xyview/GlobalXYWnd.cpp
@@ -192,23 +192,23 @@ void XYWndManager::registerCommands() {
void XYWndManager::constructPreferences()
{
- PreferencesPagePtr page = GlobalPreferenceSystem().getPage(_("Settings/Orthoview"));
-
- page->appendCheckBox("", _("View chases Mouse Cursor during Drags"), RKEY_CHASE_MOUSE);
- page->appendSlider(_("Maximum Chase Mouse Speed"), RKEY_CHASE_MOUSE_CAP, true, DEFAULT_CHASE_MOUSE_CAP, 0, 512, 1, 16, 16);
- page->appendCheckBox("", _("Update Views on Camera Movement"), RKEY_CAMERA_XY_UPDATE);
- page->appendCheckBox("", _("Show Crosshairs"), RKEY_SHOW_CROSSHAIRS);
- page->appendCheckBox("", _("Show Grid"), RKEY_SHOW_GRID);
- page->appendCheckBox("", _("Show Size Info"), RKEY_SHOW_SIZE_INFO);
- page->appendCheckBox("", _("Show Entity Angle Arrow"), RKEY_SHOW_ENTITY_ANGLES);
- page->appendCheckBox("", _("Show Entity Names"), RKEY_SHOW_ENTITY_NAMES);
- page->appendCheckBox("", _("Show Blocks"), RKEY_SHOW_BLOCKS);
- page->appendCheckBox("", _("Show Coordinates"), RKEY_SHOW_COORDINATES);
- page->appendCheckBox("", _("Show Axes"), RKEY_SHOW_AXES);
- page->appendCheckBox("", _("Show Window Outline"), RKEY_SHOW_OUTLINE);
- page->appendCheckBox("", _("Show Workzone"), RKEY_SHOW_WORKZONE);
- page->appendCheckBox("", _("Translate Manipulator always constrained to Axis"), RKEY_TRANSLATE_CONSTRAINED);
- page->appendCheckBox("", _("Higher Selection Priority for Entities"), RKEY_HIGHER_ENTITY_PRIORITY);
+ IPreferencePage& page = GlobalPreferenceSystem().getPage(_("Settings/Orthoview"));
+
+ page.appendCheckBox(_("View chases Mouse Cursor during Drags"), RKEY_CHASE_MOUSE);
+ page.appendSlider(_("Maximum Chase Mouse Speed"), RKEY_CHASE_MOUSE_CAP, 0, 512, 1, 16);
+ page.appendCheckBox(_("Update Views on Camera Movement"), RKEY_CAMERA_XY_UPDATE);
+ page.appendCheckBox(_("Show Crosshairs"), RKEY_SHOW_CROSSHAIRS);
+ page.appendCheckBox(_("Show Grid"), RKEY_SHOW_GRID);
+ page.appendCheckBox(_("Show Size Info"), RKEY_SHOW_SIZE_INFO);
+ page.appendCheckBox(_("Show Entity Angle Arrow"), RKEY_SHOW_ENTITY_ANGLES);
+ page.appendCheckBox(_("Show Entity Names"), RKEY_SHOW_ENTITY_NAMES);
+ page.appendCheckBox(_("Show Blocks"), RKEY_SHOW_BLOCKS);
+ page.appendCheckBox(_("Show Coordinates"), RKEY_SHOW_COORDINATES);
+ page.appendCheckBox(_("Show Axes"), RKEY_SHOW_AXES);
+ page.appendCheckBox(_("Show Window Outline"), RKEY_SHOW_OUTLINE);
+ page.appendCheckBox(_("Show Workzone"), RKEY_SHOW_WORKZONE);
+ page.appendCheckBox(_("Translate Manipulator always constrained to Axis"), RKEY_TRANSLATE_CONSTRAINED);
+ page.appendCheckBox(_("Higher Selection Priority for Entities"), RKEY_HIGHER_ENTITY_PRIORITY);
}
// Load/Reload the values from the registry
@@ -661,7 +661,8 @@ void XYWndManager::initialiseModule(const ApplicationContext& ctx)
GlobalUIManager().getStatusBarManager().addTextElement(
"XYZPos",
"", // no icon
- IStatusBarManager::POS_POSITION
+ IStatusBarManager::POS_POSITION,
+ _("Shows the mouse position in the orthoview")
);
XYWnd::captureStates();
diff --git a/radiant/xyview/XYRenderer.h b/radiant/xyview/XYRenderer.h
index 80d6587..6cce3fc 100644
--- a/radiant/xyview/XYRenderer.h
+++ b/radiant/xyview/XYRenderer.h
@@ -1,5 +1,4 @@
-#ifndef XYRENDERER_H_
-#define XYRENDERER_H_
+#pragma once
#include "irenderable.h"
@@ -10,11 +9,14 @@ class XYRenderer :
struct State
{
bool highlightPrimitives;
+ bool highlightAsGroupMember;
Shader* shader;
// Constructor
- State()
- : highlightPrimitives(false), shader(NULL)
+ State() :
+ highlightPrimitives(false),
+ highlightAsGroupMember(false),
+ shader(nullptr)
{}
};
@@ -23,11 +25,13 @@ class XYRenderer :
// Shader to use for highlighted objects
Shader* _selectedShader;
+ Shader* _selectedShaderGroup;
public:
- XYRenderer(RenderStateFlags globalstate, Shader* selected) :
- _globalstate(globalstate),
- _selectedShader(selected)
+ XYRenderer(RenderStateFlags globalstate, Shader* selected, Shader* selectedGroup) :
+ _globalstate(globalstate),
+ _selectedShader(selected),
+ _selectedShaderGroup(selectedGroup)
{
// Reserve space in the vector to avoid reallocation delays
_stateStack.reserve(8);
@@ -58,11 +62,17 @@ public:
_stateStack.pop_back();
}
- void highlightFaces(bool enable = true) { }
-
- void highlightPrimitives(bool enable = true)
+ void setHighlightFlag(Highlight::Flags flags, bool enabled)
{
- _stateStack.back().highlightPrimitives = enable;
+ if (flags & Highlight::Primitives)
+ {
+ _stateStack.back().highlightPrimitives = enabled;
+ }
+
+ if (flags & Highlight::GroupMember)
+ {
+ _stateStack.back().highlightAsGroupMember = enabled;
+ }
}
void addRenderable(const OpenGLRenderable& renderable,
@@ -70,9 +80,16 @@ public:
{
if (_stateStack.back().highlightPrimitives)
{
- _selectedShader->addRenderable(renderable, localToWorld);
+ if (_stateStack.back().highlightAsGroupMember)
+ {
+ _selectedShaderGroup->addRenderable(renderable, localToWorld);
+ }
+ else
+ {
+ _selectedShader->addRenderable(renderable, localToWorld);
+ }
}
- else if (_stateStack.back().shader != NULL)
+ else if (_stateStack.back().shader != nullptr)
{
_stateStack.back().shader->addRenderable(renderable, localToWorld);
}
@@ -84,9 +101,16 @@ public:
{
if (_stateStack.back().highlightPrimitives)
{
- _selectedShader->addRenderable(renderable, localToWorld, entity);
+ if (_stateStack.back().highlightAsGroupMember)
+ {
+ _selectedShaderGroup->addRenderable(renderable, localToWorld, entity);
+ }
+ else
+ {
+ _selectedShader->addRenderable(renderable, localToWorld, entity);
+ }
}
- else if (_stateStack.back().shader != NULL)
+ else if (_stateStack.back().shader != nullptr)
{
_stateStack.back().shader->addRenderable(renderable, localToWorld, entity);
}
@@ -97,5 +121,3 @@ public:
GlobalRenderSystem().render(_globalstate, modelview, projection);
}
}; // class XYRenderer
-
-#endif /*XYRENDERER_H_*/
diff --git a/radiant/xyview/XYWnd.cpp b/radiant/xyview/XYWnd.cpp
index 01917fd..acd6321 100644
--- a/radiant/xyview/XYWnd.cpp
+++ b/radiant/xyview/XYWnd.cpp
@@ -22,6 +22,7 @@
#include "ui/overlay/Overlay.h"
#include "ui/texturebrowser/TextureBrowser.h"
#include "map/RegionManager.h"
+#include "map/Map.h"
#include "selection/algorithm/General.h"
#include "selection/algorithm/Primitives.h"
#include "registry/registry.h"
@@ -70,7 +71,6 @@ XYWnd::XYWnd(int id, wxWindow* parent) :
_id(id),
_wxGLWidget(new wxutil::GLWidget(parent, std::bind(&XYWnd::onRender, this), "XYWnd")),
_drawing(false),
- _deferredDraw(std::bind(&XYWnd::performDeferredDraw, this)),
_minWorldCoord(game::current::getValue<float>("/defaults/minWorldCoord")),
_maxWorldCoord(game::current::getValue<float>("/defaults/maxWorldCoord")),
_defaultCursor(wxCURSOR_DEFAULT),
@@ -125,10 +125,6 @@ XYWnd::XYWnd(int id, wxWindow* parent) :
wxutil::FreezePointer::MouseEventFunction(),
std::bind(&XYWnd::onGLMouseButtonRelease, this, std::placeholders::_1));
- GlobalMap().signal_mapValidityChanged().connect(
- sigc::mem_fun(_deferredDraw, &DeferredDraw::onMapValidChanged)
- );
-
updateProjection();
updateModelview();
@@ -193,7 +189,7 @@ SelectionTestPtr XYWnd::createSelectionTestForPoint(const Vector2& point)
float selectEpsilon = registry::getValue<float>(RKEY_SELECT_EPSILON);
// Generate the epsilon
- DeviceVector deviceEpsilon(selectEpsilon / getWidth(), selectEpsilon / getHeight());
+ Vector2 deviceEpsilon(selectEpsilon / getWidth(), selectEpsilon / getHeight());
// Copy the current view and constrain it to a small rectangle
render::View scissored(_view);
@@ -217,12 +213,16 @@ int XYWnd::getDeviceHeight() const
return getHeight();
}
-void XYWnd::captureStates() {
+void XYWnd::captureStates()
+{
_selectedShader = GlobalRenderSystem().capture("$XY_OVERLAY");
+ _selectedShaderGroup = GlobalRenderSystem().capture("$XY_OVERLAY_GROUP");
}
-void XYWnd::releaseStates() {
- _selectedShader = ShaderPtr();
+void XYWnd::releaseStates()
+{
+ _selectedShader.reset();
+ _selectedShaderGroup.reset();
}
const std::string XYWnd::getViewTypeTitle(EViewType viewtype) {
@@ -268,7 +268,7 @@ void XYWnd::queueDraw()
return; // deny redraw requests if we're currently drawing
}
- _deferredDraw.draw();
+ _wxGLWidget->Refresh(false);
}
void XYWnd::onSceneGraphChange() {
@@ -931,9 +931,10 @@ void XYWnd::drawGrid()
}
}
-void XYWnd::drawBlockGrid() {
- if (GlobalMap().findWorldspawn() == NULL) {
- return;
+void XYWnd::drawBlockGrid()
+{
+ if (GlobalMap().getWorldspawn() == NULL) {
+ return; // no worldspawn yet
}
// Set a default blocksize of 1024
int blockSize = GlobalXYWnd().defaultBlockSize();
@@ -1306,7 +1307,7 @@ void XYWnd::draw()
{
// Construct the renderer and render the scene
- XYRenderer renderer(flagsMask, _selectedShader.get());
+ XYRenderer renderer(flagsMask, _selectedShader.get(), _selectedShaderGroup.get());
// First pass (scenegraph traversal)
render::RenderableCollectionWalker::collectRenderablesInScene(renderer,
@@ -1514,11 +1515,6 @@ void XYWnd::onIdle(wxIdleEvent& ev)
}
}
-void XYWnd::performDeferredDraw()
-{
- _wxGLWidget->Refresh(false);
-}
-
void XYWnd::onGLResize(wxSizeEvent& ev)
{
const wxSize clientSize = _wxGLWidget->GetClientSize();
@@ -1533,7 +1529,7 @@ void XYWnd::onGLResize(wxSizeEvent& ev)
void XYWnd::onRender()
{
- if (GlobalMap().isValid() && GlobalMainFrame().screenUpdatesEnabled())
+ if (GlobalMainFrame().screenUpdatesEnabled())
{
util::ScopedBoolLock drawLock(_drawing);
@@ -1659,5 +1655,6 @@ IInteractiveView& XYWnd::getInteractiveView()
/* STATICS */
ShaderPtr XYWnd::_selectedShader;
+ShaderPtr XYWnd::_selectedShaderGroup;
} // namespace
diff --git a/radiant/xyview/XYWnd.h b/radiant/xyview/XYWnd.h
index 57644f1..48f919b 100644
--- a/radiant/xyview/XYWnd.h
+++ b/radiant/xyview/XYWnd.h
@@ -13,7 +13,6 @@
#include <wx/cursor.h>
#include <wx/stopwatch.h>
-#include "map/DeferredDraw.h"
#include "camera/CameraObserver.h"
#include "render/View.h"
#include "imousetool.h"
@@ -37,8 +36,6 @@ protected:
wxutil::GLWidget* _wxGLWidget;
bool _drawing;
- DeferredDraw _deferredDraw;
-
// The maximum/minimum values of a coordinate
double _minWorldCoord;
double _maxWorldCoord;
@@ -60,6 +57,7 @@ protected:
// Shader to use for selected items
static ShaderPtr _selectedShader;
+ static ShaderPtr _selectedShaderGroup;
Vector3 _mousePosition;
@@ -189,9 +187,6 @@ private:
// Active mousetools might capture the mouse, this is handled here
void handleGLCapturedMouseMotion(const MouseToolPtr& tool, int x, int y, unsigned int state);
- // Is called by the DeferredDraw helper
- void performDeferredDraw();
-
// wxGLWidget-attached render method
void onRender();
void onGLResize(wxSizeEvent& ev);
diff --git a/tools/i18n/darkradiant.pot b/tools/i18n/darkradiant.pot
index b55290c..9f99a86 100644
--- a/tools/i18n/darkradiant.pot
+++ b/tools/i18n/darkradiant.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: greebo at angua.at\n"
-"POT-Creation-Date: 2016-01-05 11:54+0100\n"
+"POT-Creation-Date: 2016-11-18 18:32+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
"Language-Team: LANGUAGE <LL at li.org>\n"
@@ -79,11 +79,11 @@ msgstr ""
msgid "Solid selection boxes"
msgstr ""
-#: ..\..\radiant\camera\CameraSettings.cpp:75
+#: ..\..\radiant\camera\CameraSettings.cpp:74
msgid "Show camera toolbar"
msgstr ""
-#: ..\..\radiant\camera\FloatingCamWnd.cpp:18 xml_file_content.cpp:60
+#: ..\..\radiant\camera\FloatingCamWnd.cpp:18 xml_file_content.cpp:61
msgid "Camera"
msgstr ""
@@ -95,27 +95,31 @@ msgstr ""
msgid "Jump to Object"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:97
+#: ..\..\radiant\camera\tools\PanViewTool.h:23
+msgid "Pan Camera View"
+msgstr ""
+
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:116
msgid "Pick Shader"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:120
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:139
msgid "Paste Shader Projected"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:138
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:158
msgid "Paste Shader Natural"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:156
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:177
msgid "Paste Texture Coordinates"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:174
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:196
msgid "Paste Shader to all Brush Faces"
msgstr ""
-#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:192
+#: ..\..\radiant\camera\tools\ShaderClipboardTools.h:215
msgid "Paste Shader Name"
msgstr ""
@@ -131,40 +135,40 @@ msgstr ""
msgid "Caulk shader name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:34
+#: ..\..\radiant\layers\LayerSystem.cpp:36
msgid "Default"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:37
+#: ..\..\radiant\layers\LayerSystem.cpp:39
msgid "Create Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:39
+#: ..\..\radiant\layers\LayerSystem.cpp:41
msgid "Add to Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:40
+#: ..\..\radiant\layers\LayerSystem.cpp:42
msgid "Move to Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:41
+#: ..\..\radiant\layers\LayerSystem.cpp:43
msgid "Remove from Layer..."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:536
+#: ..\..\radiant\layers\LayerSystem.cpp:550
#: ..\..\plugins\particles\editor\ParticleEditor.cpp:1537
msgid "Enter Name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:537
+#: ..\..\radiant\layers\LayerSystem.cpp:551
msgid "Enter Layer Name"
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:549
+#: ..\..\radiant\layers\LayerSystem.cpp:563
msgid "Cannot create layer with empty name."
msgstr ""
-#: ..\..\radiant\layers\LayerSystem.cpp:563
+#: ..\..\radiant\layers\LayerSystem.cpp:577
msgid "This name already exists."
msgstr ""
@@ -195,33 +199,39 @@ msgstr ""
msgid "Loading entity %d\n"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:299
+#: ..\..\radiant\map\AutoSaver.cpp:276
msgid "Settings/Autosave"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:302
+#: ..\..\radiant\map\AutoSaver.cpp:279
msgid "Enable Autosave"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:303
+#: ..\..\radiant\map\AutoSaver.cpp:280
msgid "Autosave Interval (in minutes)"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:305
+#: ..\..\radiant\map\AutoSaver.cpp:282
msgid "Save Snapshots"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:306
+#: ..\..\radiant\map\AutoSaver.cpp:283
msgid "Snapshot folder (relative to map folder)"
msgstr ""
-#: ..\..\radiant\map\AutoSaver.cpp:307
+#: ..\..\radiant\map\AutoSaver.cpp:284
msgid "Max Snapshot Folder size (MB)"
msgstr ""
-#: ..\..\radiant\map\CounterManager.cpp:67
+#: ..\..\radiant\map\CounterManager.cpp:63
+msgid ""
+"Number of brushes/patches/entities in this map\n"
+"(Number of selected items shown in parentheses)"
+msgstr ""
+
+#: ..\..\radiant\map\CounterManager.cpp:81
#, c-format
-msgid "Brushes: %lu Patches: %lu Entities: %lu"
+msgid "Brushes: %lu (%lu) Patches: %lu (%lu) Entities: %lu (%lu)"
msgstr ""
#: ..\..\radiant\map\FindMapElements.cpp:95
@@ -236,92 +246,92 @@ msgstr ""
msgid "Brush Number:"
msgstr ""
-#: ..\..\radiant\map\InfoFile.cpp:73
+#: ..\..\radiant\map\infofile\InfoFile.cpp:70
msgid "Map Info File Version invalid"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:59
+#: ..\..\radiant\map\Map.cpp:62
msgid "unnamed.map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:182 ..\..\radiant\map\Map.cpp:518
-#: ..\..\radiant\map\Map.cpp:610 ..\..\radiant\map\Map.cpp:638
-#: ..\..\radiant\RadiantModule.cpp:134
+#: ..\..\radiant\map\Map.cpp:106 ..\..\radiant\map\Map.cpp:431
+#: ..\..\radiant\map\Map.cpp:522 ..\..\radiant\map\Map.cpp:550
+#: ..\..\radiant\RadiantModule.cpp:135
#: ..\..\radiant\referencecache\ModelCache.cpp:245
#: ..\..\radiant\referencecache\ModelCache.cpp:261
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Processing..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:182
+#: ..\..\radiant\map\Map.cpp:106
msgid "Loading textures..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:518
+#: ..\..\radiant\map\Map.cpp:431
msgid "Saving Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:569
+#: ..\..\radiant\map\Map.cpp:481
msgid "Importing..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:664
+#: ..\..\radiant\map\Map.cpp:576
#, c-format
msgid ""
"Save changes to map \"%s\"\n"
"before closing?"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:672
+#: ..\..\radiant\map\Map.cpp:584
#, c-format
msgid "%d minutes"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:676
+#: ..\..\radiant\map\Map.cpp:588
#, c-format
msgid "%d seconds"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:680
+#: ..\..\radiant\map\Map.cpp:592
#, c-format
msgid ""
"If you don't save, changes from the last %s\n"
"will be lost."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:738
+#: ..\..\radiant\map\Map.cpp:650
msgid "Save Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:778
+#: ..\..\radiant\map\Map.cpp:690
msgid "Save Copy As..."
msgstr ""
-#: ..\..\radiant\map\Map.cpp:854
+#: ..\..\radiant\map\Map.cpp:781
msgid "New Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:865 ..\..\radiant\ui\mru\MRU.cpp:93
+#: ..\..\radiant\map\Map.cpp:790 ..\..\radiant\ui\mru\MRU.cpp:93
msgid "Open Map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:869
+#: ..\..\radiant\map\Map.cpp:794
msgid "Open map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:883
+#: ..\..\radiant\map\Map.cpp:808
msgid "Import map"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:912
+#: ..\..\radiant\map\Map.cpp:837
msgid "Export selection"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:927
+#: ..\..\radiant\map\Map.cpp:852
msgid "Save selected as Prefab"
msgstr ""
-#: ..\..\radiant\map\Map.cpp:1008
+#: ..\..\radiant\map\Map.cpp:933
#, c-format
msgid ""
"Failure reading map from clipboard:\n"
@@ -332,39 +342,32 @@ msgstr ""
msgid "Map"
msgstr ""
-#: ..\..\radiant\map\MapFileManager.cpp:36 xml_file_content.cpp:89
+#: ..\..\radiant\map\MapFileManager.cpp:36 xml_file_content.cpp:90
msgid "Region"
msgstr ""
#: ..\..\radiant\map\MapFileManager.cpp:37
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:327
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:343
msgid "Prefab"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:273 ..\..\radiant\map\MapResource.cpp:641
+#: ..\..\radiant\map\MapResource.cpp:257 ..\..\radiant\map\MapResource.cpp:529
#, c-format
msgid "File is write-protected: %s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:434
-#, c-format
-msgid ""
-"Failure opening map file:\n"
-"%s"
-msgstr ""
-
-#: ..\..\radiant\map\MapResource.cpp:476
+#: ..\..\radiant\map\MapResource.cpp:363
#, c-format
msgid ""
"Could not determine map format of file:\n"
"%s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:602
+#: ..\..\radiant\map\MapResource.cpp:410
msgid "Map loading cancelled"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:614
+#: ..\..\radiant\map\MapResource.cpp:422
#, c-format
msgid ""
"Failure reading map file:\n"
@@ -373,40 +376,47 @@ msgid ""
"%s"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:706
+#: ..\..\radiant\map\MapResource.cpp:485 ..\..\radiant\map\MapResource.cpp:504
+#, c-format
+msgid ""
+"Failure opening file:\n"
+"%s"
+msgstr ""
+
+#: ..\..\radiant\map\MapResource.cpp:594
msgid "Map writing cancelled"
msgstr ""
-#: ..\..\radiant\map\MapResource.cpp:721
+#: ..\..\radiant\map\MapResource.cpp:609
msgid "Could not open output streams for writing"
msgstr ""
-#: ..\..\radiant\map\PointFile.cpp:116
+#: ..\..\radiant\map\PointFile.cpp:126
#, c-format
msgid "Could not open pointfile: %s"
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:203
+#: ..\..\radiant\map\RegionManager.cpp:173
msgid "Warning: Camera not within region, can't set info_player_start."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:293
+#: ..\..\radiant\map\RegionManager.cpp:261
msgid "Could not set Region: XY Top View not found."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:320
+#: ..\..\radiant\map\RegionManager.cpp:288
msgid "Could not set Region: please select a single Brush."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:345
+#: ..\..\radiant\map\RegionManager.cpp:313
msgid "This command is not available in component mode."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:351
+#: ..\..\radiant\map\RegionManager.cpp:319
msgid "Could not set Region: nothing selected."
msgstr ""
-#: ..\..\radiant\map\RegionManager.cpp:368
+#: ..\..\radiant\map\RegionManager.cpp:336
msgid "Export region"
msgstr ""
@@ -423,7 +433,7 @@ msgstr ""
msgid "Initialising Modules"
msgstr ""
-#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:165
+#: ..\..\radiant\modulesystem\ModuleRegistry.cpp:162
msgid "Modules initialised"
msgstr ""
@@ -455,7 +465,7 @@ msgstr ""
msgid "Cannot create cylinder-cap, patch must have a width of 9."
msgstr ""
-#: ..\..\radiant\patch\Patch.cpp:1667
+#: ..\..\radiant\patch\Patch.cpp:1639
msgid "Sorry. Patch is not suitable for this kind of operation."
msgstr ""
@@ -471,11 +481,11 @@ msgstr ""
#: ..\..\radiant\settings\GameManager.cpp:97
#: ..\..\radiant\settings\GameManager.cpp:323
#: ..\..\radiant\settings\GameManager.cpp:344
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:198
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:169
msgid "Game"
msgstr ""
-#: ..\..\radiant\RadiantModule.cpp:238
+#: ..\..\radiant\RadiantModule.cpp:239
msgid "Settings"
msgstr ""
@@ -508,41 +518,82 @@ msgstr ""
msgid "Can't convert curves - no entities with curves selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:62
+#: ..\..\radiant\selection\algorithm\Entity.cpp:82
+#, c-format
+msgid "The name %s already exists in this map!"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:106
+msgid "Cannot set classname to an empty string."
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:112
+msgid "Cannot change classname to worldspawn."
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Entity.cpp:131
msgid "Cannot change classname of worldspawn entity."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:104
+#: ..\..\radiant\selection\algorithm\Entity.cpp:169
msgid "Critical: Cannot find selected entities."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:109
-#: ..\..\radiant\selection\algorithm\Entity.cpp:125
+#: ..\..\radiant\selection\algorithm\Entity.cpp:174
+#: ..\..\radiant\selection\algorithm\Entity.cpp:190
msgid "Exactly two entities must be selected for this operation."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Entity.cpp:171
+#: ..\..\radiant\selection\algorithm\Entity.cpp:236
#, c-format
msgid "Unable to create entity %s, no brushes selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Group.cpp:236
+#: ..\..\radiant\selection\algorithm\Group.cpp:234
msgid ""
"Cannot reparent primitives to entity. Please select at least one brush/patch "
"and exactly one entity.(The entity has to be selected last.)"
msgstr ""
-#: ..\..\radiant\selection\algorithm\Group.cpp:386
+#: ..\..\radiant\selection\algorithm\Group.cpp:384
msgid ""
"Cannot merge entities, the selection must consist of func_* entities only.\n"
"(The first selected entity will be preserved.)"
msgstr ""
+#: ..\..\radiant\selection\algorithm\Group.cpp:394
+msgid "Groups can be formed in Primitive selection mode only"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:399
+msgid "Nothing selected, cannot group anything"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:404
+msgid "Select more than one element to form a group"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:430
+msgid "The selected elements already form a group"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:455
+msgid "Groups can be dissolved in Primitive selection mode only"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:460
+msgid "Nothing selected, cannot un-group anything"
+msgstr ""
+
+#: ..\..\radiant\selection\algorithm\Group.cpp:480
+msgid "The selected elements aren't part of any group"
+msgstr ""
+
#: ..\..\radiant\selection\algorithm\Patch.cpp:60
msgid "Cannot create caps, no patches selected."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Patch.cpp:208
+#: ..\..\radiant\selection\algorithm\Patch.cpp:197
msgid "Cannot thicken patch. Nothing selected."
msgstr ""
@@ -573,42 +624,52 @@ msgstr ""
msgid "At least one brush must be selected for this operation."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:285
+#: ..\..\radiant\selection\algorithm\Shader.cpp:307
msgid ""
"Can't paste shader to entire brush.\n"
"Target is not a brush."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:320
+#: ..\..\radiant\selection\algorithm\Shader.cpp:346
msgid ""
"Can't paste Texture Coordinates.\n"
"Target patch dimensions must match."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:327
+#: ..\..\radiant\selection\algorithm\Shader.cpp:355
msgid "Can't paste Texture Coordinates from patches to faces."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:332
+#: ..\..\radiant\selection\algorithm\Shader.cpp:361
msgid "Can't paste Texture Coordinates from faces."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:388
+#: ..\..\radiant\selection\algorithm\Shader.cpp:417
msgid "Can't copy Shader. Couldn't retrieve patch."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:398
+#: ..\..\radiant\selection\algorithm\Shader.cpp:427
msgid "Can't copy Shader. Couldn't retrieve face."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Shader.cpp:404
+#: ..\..\radiant\selection\algorithm\Shader.cpp:433
msgid "Can't copy Shader. Please select a single face or patch."
msgstr ""
-#: ..\..\radiant\selection\algorithm\Transformation.cpp:55
+#: ..\..\radiant\selection\algorithm\Transformation.cpp:56
msgid "Cannot scale by zero value."
msgstr ""
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:81
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:97
+msgid "Ungroup Selection"
+msgstr ""
+
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:84
+#: ..\..\radiant\selection\group\SelectionGroupManager.cpp:91
+msgid "Group Selection"
+msgstr ""
+
#: ..\..\radiant\selection\ManipulateMouseTool.cpp:28
msgid "Manipulate"
msgstr ""
@@ -617,31 +678,31 @@ msgstr ""
msgid "Select"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:168 xml_file_content.cpp:4
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:175 xml_file_content.cpp:4
msgid "Select Faces"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:187
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:194
msgid "Cycle Selection"
msgstr ""
-#: ..\..\radiant\selection\SelectionMouseTools.cpp:233
+#: ..\..\radiant\selection\SelectionMouseTools.cpp:247
msgid "Cycle Face Selection"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:84
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:104
msgid "Selection Set: "
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:92
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:112
msgid "Clear Selection Sets"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:194
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:214
msgid "Delete all selection sets?"
msgstr ""
-#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:195
+#: ..\..\radiant\selection\selectionset\SelectionSetManager.cpp:215
msgid ""
"This will delete all set definitions. The actual map objects will not be "
"affected by this step.\n"
@@ -669,20 +730,24 @@ msgid ""
"scene."
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:87
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:24
+msgid "The name of the shader in the clipboard"
+msgstr ""
+
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:91
#, c-format
msgid "ShaderClipboard: %s"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:90
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:94
msgid "Face"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:93
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:97
msgid "Patch"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:96
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
#: ..\..\radiant\ui\common\ShaderSelector.cpp:359
#: ..\..\radiant\ui\common\TexturePreviewCombo.cpp:73
#: ..\..\radiant\ui\mapinfo\ShaderInfoTab.cpp:60
@@ -690,7 +755,7 @@ msgstr ""
msgid "Shader"
msgstr ""
-#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:100
+#: ..\..\radiant\selection\shaderclipboard\ShaderClipboard.cpp:104
msgid "ShaderClipboard is empty."
msgstr ""
@@ -1487,10 +1552,35 @@ msgstr ""
msgid "Zulu"
msgstr ""
+#: ..\..\radiant\settings\PreferencePage.cpp:19
+#, c-format
+msgid "%s Settings"
+msgstr ""
+
#: ..\..\radiant\textool\TexTool.cpp:38
msgid "Texture Tool"
msgstr ""
+#: ..\..\radiant\ui\aas\AasControl.cpp:36
+msgid "Reload AAS File"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:30
+msgid "AAS Viewer"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:80
+msgid "Search for AAS Files"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:84
+msgid "Show Area Numbers"
+msgstr ""
+
+#: ..\..\radiant\ui\aas\AasControlDialog.cpp:87
+msgid "Hide distant Areas"
+msgstr ""
+
#: ..\..\radiant\ui\about\AboutDialog.cpp:24
msgid "About DarkRadiant"
msgstr ""
@@ -1521,7 +1611,7 @@ msgid "Renderer: %s"
msgstr ""
#: ..\..\radiant\ui\animationpreview\MD5AnimationViewer.cpp:16
-#: xml_file_content.cpp:139
+#: xml_file_content.cpp:140
msgid "MD5 Animation Viewer"
msgstr ""
@@ -1556,7 +1646,7 @@ msgid "Shortcut List"
msgstr ""
#: ..\..\radiant\ui\commandlist\CommandList.cpp:53
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:94
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:116
#: xml_file_content.cpp:2
msgid "Command"
msgstr ""
@@ -1630,7 +1720,7 @@ msgstr ""
#: ..\..\radiant\ui\common\ShaderSelector.cpp:195
#: ..\..\radiant\ui\common\ShaderSelector.cpp:225
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:437
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:481
#: ..\..\plugins\eclasstree\EClassTree.cpp:143
#: ..\..\libs\wxutil\KeyValueTable.cpp:44
msgid "Value"
@@ -1678,7 +1768,7 @@ msgstr ""
#: ..\..\radiant\ui\common\SoundChooser.cpp:189
#: ..\..\radiant\ui\entitychooser\EntityClassChooser.cpp:290
#: ..\..\radiant\ui\modelselector\ModelSelector.cpp:340
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:380
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:396
msgid "Loading..."
msgstr ""
@@ -1711,12 +1801,12 @@ msgid "Custom properties defined for this entity class, if any"
msgstr ""
#: ..\..\radiant\ui\einspector\AddPropertyDialog.cpp:76
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:432
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:476
#: ..\..\plugins\eclasstree\EClassTree.cpp:140
msgid "Property"
msgstr ""
-#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:25
+#: ..\..\radiant\ui\einspector\ClassnamePropertyEditor.cpp:26
msgid "Choose entity class..."
msgstr ""
@@ -1728,41 +1818,42 @@ msgstr ""
msgid "Show help"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:292
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:312
msgid "Add property..."
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:296
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:317
msgid "Delete property"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:304
-msgid "Copy Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:325
+msgid "Copy Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:309
-msgid "Cut Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:330
+msgid "Cut Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:314
-msgid "Paste Spawnarg"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:335
+msgid "Paste Spawnarg(s)"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:442
-msgid "?"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:347
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:350
+#: ..\..\plugins\uimanager\GroupDialog.cpp:28
+msgid "Entity"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:654
-#, c-format
-msgid "The name %s already exists in this map!"
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:486
+msgid "?"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1064
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1200
#, c-format
msgid "Entity %d"
msgstr ""
-#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1076
+#: ..\..\radiant\ui\einspector\EntityInspector.cpp:1212
#, c-format
msgid "Entity %d, Primitive %d"
msgstr ""
@@ -1771,7 +1862,7 @@ msgstr ""
msgid "Choose target entity..."
msgstr ""
-#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:78
+#: ..\..\radiant\ui\einspector\FloatPropertyEditor.cpp:71
#: ..\..\radiant\ui\einspector\Vector3PropertyEditor.cpp:62
msgid "Apply..."
msgstr ""
@@ -2033,59 +2124,53 @@ msgstr ""
msgid "Window Layout"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:93
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:84
msgid "Settings/Multi Monitor"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:112
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:103
msgid "Start DarkRadiant on monitor"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:131
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:122
msgid "Settings/Compatibility"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:133
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:124
msgid "Disable Windows Desktop Composition"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:267
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:256
msgid "Exit DarkRadiant"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:380
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:383
-#: ..\..\plugins\uimanager\GroupDialog.cpp:28
-msgid "Entity"
-msgstr ""
-
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:391
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:394
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:369
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:372
msgid "Media"
msgstr ""
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:402
-#: ..\..\radiant\ui\mainframe\MainFrame.cpp:405
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:381
+#: ..\..\radiant\ui\mainframe\MainFrame.cpp:384
msgid "Console"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:144
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:145
msgid "Camera Position"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:147
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:148
msgid "Top Left"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:149
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:150
msgid "Top Right"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:151
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:152
msgid "Bottom Left"
msgstr ""
-#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:153
+#: ..\..\radiant\ui\mainframe\SplitPaneLayout.cpp:154
msgid "Bottom Right"
msgstr ""
@@ -2381,7 +2466,7 @@ msgstr ""
msgid "Merge Entities"
msgstr ""
-#: ..\..\radiant\ui\ortho\OrthoContextMenu.cpp:74 xml_file_content.cpp:155
+#: ..\..\radiant\ui\ortho\OrthoContextMenu.cpp:74 xml_file_content.cpp:156
msgid "Make Visportal"
msgstr ""
@@ -2455,7 +2540,7 @@ msgid "Patch Inspector"
msgstr ""
#: ..\..\radiant\ui\patch\PatchInspector.cpp:29
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:55
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:56
#: ..\..\radiant\ui\transform\TransformDialog.cpp:38
msgid "Step:"
msgstr ""
@@ -2464,135 +2549,139 @@ msgstr ""
msgid "Patch Thicken"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:41
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:42
msgid "Choose Prefab"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:97
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:100
msgid "Rescan Prefab Folders"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:128
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:105
+msgid "Create Group out of Prefab parts"
+msgstr ""
+
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:140
msgid "Browse mod resources"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:131
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:143
msgid "Select recently used path:"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:133
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:145
msgid "Browse custom path:"
msgstr ""
-#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:532
+#: ..\..\radiant\ui\prefabselector\PrefabSelector.cpp:553
msgid "<no description>"
msgstr ""
-#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:37
+#: ..\..\radiant\ui\prefdialog\PrefDialog.cpp:23
msgid "DarkRadiant Preferences"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:38
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
msgid "Surface Inspector"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:39
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
msgid "Texture Properties"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:40
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:41
msgid "Texture Operations"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:48
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
msgid "Horiz. Shift:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:49
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
msgid "Vert. Shift:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:50
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
msgid "Horiz. Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:51
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
msgid "Vert. Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:52
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
msgid "Rotation:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:53
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:54
#: xml_file_content.cpp:15
msgid "Shader:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:57
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
msgid "Fit Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:58
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:59
msgid "Fit"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:60
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
msgid "Align Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:61
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
msgid "Top"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:62
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
msgid "Bottom"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:63
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
#: xml_file_content.cpp:16
msgid "Right"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:64
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:65
#: xml_file_content.cpp:15
msgid "Left"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:66
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
msgid "Flip Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:67
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
msgid "Flip Horizontal"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:68
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:69
msgid "Flip Vertical"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:70
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
msgid "Modify Texture:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:71
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
msgid "Natural"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:72
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:73
msgid "Normalise"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:74
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
msgid "Default Scale:"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:75
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:76
#: xml_file_content.cpp:9
msgid "Texture Lock"
msgstr ""
-#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:634
+#: ..\..\radiant\ui\surfaceinspector\SurfaceInspector.cpp:649
msgid "Both fit values must be > 0."
msgstr ""
@@ -2601,7 +2690,7 @@ msgid "Seek in Media Browser"
msgstr ""
#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:269
-#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:811
+#: ..\..\radiant\ui\texturebrowser\TextureBrowser.cpp:809
msgid "No shader"
msgstr ""
@@ -2701,7 +2790,7 @@ msgstr ""
msgid "Show Entity Names"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:205 xml_file_content.cpp:79
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:205 xml_file_content.cpp:80
msgid "Show Blocks"
msgstr ""
@@ -2709,15 +2798,15 @@ msgstr ""
msgid "Show Coordinates"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:207 xml_file_content.cpp:82
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:207 xml_file_content.cpp:83
msgid "Show Axes"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:208 xml_file_content.cpp:81
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:208 xml_file_content.cpp:82
msgid "Show Window Outline"
msgstr ""
-#: ..\..\radiant\xyview\GlobalXYWnd.cpp:209 xml_file_content.cpp:83
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:209 xml_file_content.cpp:84
msgid "Show Workzone"
msgstr ""
@@ -2729,6 +2818,10 @@ msgstr ""
msgid "Higher Selection Priority for Entities"
msgstr ""
+#: ..\..\radiant\xyview\GlobalXYWnd.cpp:665
+msgid "Shows the mouse position in the orthoview"
+msgstr ""
+
#: ..\..\radiant\xyview\tools\BrushCreatorTool.cpp:25
msgid "Drag-create Brush"
msgstr ""
@@ -2741,7 +2834,7 @@ msgstr ""
msgid "Drag Camera"
msgstr ""
-#: ..\..\radiant\xyview\tools\ClipperTool.cpp:21 xml_file_content.cpp:149
+#: ..\..\radiant\xyview\tools\ClipperTool.cpp:21 xml_file_content.cpp:150
#: xml_file_content.cpp:12 xml_file_content.cpp:17
msgid "Clipper"
msgstr ""
@@ -2766,7 +2859,7 @@ msgstr ""
msgid "YZ Side"
msgstr ""
-#: ..\..\radiant\xyview\XYWnd.cpp:637
+#: ..\..\radiant\xyview\XYWnd.cpp:498
#, c-format
msgid "x: %6.1lf y: %6.1lf z: %6.1lf"
msgstr ""
@@ -2785,7 +2878,7 @@ msgstr ""
msgid "Conversation Editor"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:278
+#: ..\..\plugins\dm.conversation\ConversationDialog.cpp:280
#, c-format
msgid "Unable to create conversation Entity: class '%s' not found."
msgstr ""
@@ -2794,35 +2887,35 @@ msgstr ""
msgid "Edit Conversation"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:67
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:89
msgid "Actor (click to edit)"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:92
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:114
#: xml_file_content.cpp:1
msgid "Actor"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:96
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:118
msgid "Wait"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:201
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:223
#, c-format
msgid "Actor %d"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "yes"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:203
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:225
#: ..\..\plugins\dm.stimresponse\ResponseEffect.cpp:206
msgid "no"
msgstr ""
-#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:369
+#: ..\..\plugins\dm.conversation\ConversationEditor.cpp:394
msgid "New Actor"
msgstr ""
@@ -3941,7 +4034,7 @@ msgstr ""
#: ..\..\plugins\dm.stimresponse\ResponseEditor.cpp:412
#: ..\..\plugins\dm.stimresponse\StimEditor.cpp:403
#: ..\..\plugins\uimanager\colourscheme\ColourSchemeEditor.cpp:95
-#: xml_file_content.cpp:179 xml_file_content.cpp:3 xml_file_content.cpp:7
+#: xml_file_content.cpp:180 xml_file_content.cpp:3 xml_file_content.cpp:7
#: xml_file_content.cpp:9 xml_file_content.cpp:15 xml_file_content.cpp:2
#: xml_file_content.cpp:5 xml_file_content.cpp:6 xml_file_content.cpp:18
msgid "Delete"
@@ -4069,7 +4162,8 @@ msgstr ""
msgid "Custom Stims"
msgstr ""
-#: ..\..\plugins\eclassmgr\EClassManager.cpp:330
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:327
+#: ..\..\plugins\eclassmgr\EClassManager.cpp:328
msgid "Reloading Defs"
msgstr ""
@@ -4113,47 +4207,51 @@ msgstr ""
msgid "All Files"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:151
+#: ..\..\plugins\grid\Grid.cpp:55
+msgid "Current Grid Size"
+msgstr ""
+
+#: ..\..\plugins\grid\Grid.cpp:152
msgid "Settings/Grid"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:153
+#: ..\..\plugins\grid\Grid.cpp:154
msgid "Default Grid Size"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:157
+#: ..\..\plugins\grid\Grid.cpp:158
msgid "Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:158
+#: ..\..\plugins\grid\Grid.cpp:159
msgid "Dotted Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:159
+#: ..\..\plugins\grid\Grid.cpp:160
msgid "More Dotted Lines"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:160
+#: ..\..\plugins\grid\Grid.cpp:161
msgid "Crosses"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:161
+#: ..\..\plugins\grid\Grid.cpp:162
msgid "Dots"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:162
+#: ..\..\plugins\grid\Grid.cpp:163
msgid "Big Dots"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:163
+#: ..\..\plugins\grid\Grid.cpp:164
msgid "Squares"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:165
+#: ..\..\plugins\grid\Grid.cpp:166
msgid "Major Grid Style"
msgstr ""
-#: ..\..\plugins\grid\Grid.cpp:166
+#: ..\..\plugins\grid\Grid.cpp:167
msgid "Minor Grid Style"
msgstr ""
@@ -4182,24 +4280,25 @@ msgid "Incorrect map version: required %f, found %f"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:144
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:94
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:102
#, c-format
msgid "Primitive #%d: parse error"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:154
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:104
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:112
#, c-format
msgid "Primitive #%d: parse exception %s"
msgstr ""
#: ..\..\plugins\mapdoom3\Doom3MapReader.cpp:245
-#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:195
+#: ..\..\plugins\mapdoom3\Quake3MapReader.cpp:203
#, c-format
msgid "Parsed invalid value '%s' for key '%s'"
msgstr ""
#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:125
+#: ..\..\plugins\mapdoom3\primitiveparsers\BrushDef.cpp:234
#, c-format
msgid "BrushDefParser: invalid token '%s'"
msgstr ""
@@ -4269,23 +4368,23 @@ msgstr ""
msgid "Cannot save particle, it has not been registered yet."
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:316
-#: ..\..\plugins\particles\ParticlesManager.cpp:344
+#: ..\..\plugins\particles\ParticlesManager.cpp:325
+#: ..\..\plugins\particles\ParticlesManager.cpp:353
#, c-format
msgid "Cannot open file for writing: %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:357
+#: ..\..\plugins\particles\ParticlesManager.cpp:366
#, c-format
msgid "Cannot open file for reading: %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:404
+#: ..\..\plugins\particles\ParticlesManager.cpp:413
#, c-format
msgid "Could not remove the file %s"
msgstr ""
-#: ..\..\plugins\particles\ParticlesManager.cpp:418
+#: ..\..\plugins\particles\ParticlesManager.cpp:427
#, c-format
msgid "Could not rename the temporary file %s"
msgstr ""
@@ -4299,7 +4398,7 @@ msgstr ""
msgid "Reload Scripts"
msgstr ""
-#: ..\..\plugins\script\ScriptMenu.cpp:51
+#: ..\..\plugins\script\ScriptMenu.cpp:60
msgid "No scripts available"
msgstr ""
@@ -4311,7 +4410,7 @@ msgstr ""
msgid "Run Script"
msgstr ""
-#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:319
+#: ..\..\plugins\shaders\Doom3ShaderSystem.cpp:321
msgid "Loading Shaders"
msgstr ""
@@ -4350,20 +4449,16 @@ msgstr ""
msgid "_Filters"
msgstr ""
-#: ..\..\plugins\undo\UndoSystem.cpp:384
-msgid "Settings/Undo System"
+#: ..\..\plugins\uimanager\UIManager.cpp:115
+msgid "Describes available Mouse Commands"
msgstr ""
-#: ..\..\plugins\undo\UndoSystem.cpp:385
-msgid "Undo Queue Size"
-msgstr ""
-
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:31
-msgid "Save as Obj"
+#: ..\..\plugins\undo\UndoSystem.cpp:398
+msgid "Settings/Undo System"
msgstr ""
-#: ..\..\plugins\wavefront\WaveFrontModule.cpp:89
-msgid "Export Selection as OBJ..."
+#: ..\..\plugins\undo\UndoSystem.cpp:399
+msgid "Undo Queue Size"
msgstr ""
#: ..\..\libs\wxutil\dialog\MessageBox.cpp:20 xml_file_content.cpp:8
@@ -4502,7 +4597,7 @@ msgstr ""
msgid "Reload S&kins"
msgstr ""
-#: xml_file_content.cpp:16 xml_file_content.cpp:26
+#: xml_file_content.cpp:16 xml_file_content.cpp:28
msgid "Reload Materials"
msgstr ""
@@ -4662,496 +4757,496 @@ msgstr ""
msgid "&Texture Tool"
msgstr ""
-#: xml_file_content.cpp:61
-msgid "&Center"
+#: xml_file_content.cpp:60
+msgid "AAS Area Viewer"
msgstr ""
#: xml_file_content.cpp:62
-msgid "&Up Floor"
+msgid "&Center"
msgstr ""
#: xml_file_content.cpp:63
-msgid "&Down Floor"
+msgid "&Up Floor"
msgstr ""
#: xml_file_content.cpp:64
-msgid "Far Clip Plane In"
+msgid "&Down Floor"
msgstr ""
#: xml_file_content.cpp:65
-msgid "Far Clip Plane Out"
+msgid "Far Clip Plane In"
msgstr ""
#: xml_file_content.cpp:66
-msgid "Next leak spot"
+msgid "Far Clip Plane Out"
msgstr ""
#: xml_file_content.cpp:67
-msgid "Previous leak spot"
+msgid "Next leak spot"
msgstr ""
#: xml_file_content.cpp:68
-msgid "Orthographic"
+msgid "Previous leak spot"
msgstr ""
#: xml_file_content.cpp:69
-msgid "Next (XY, XZ, YZ)"
+msgid "Orthographic"
msgstr ""
#: xml_file_content.cpp:70
-msgid "XY (Top)"
+msgid "Next (XY, XZ, YZ)"
msgstr ""
#: xml_file_content.cpp:71
-msgid "YZ"
+msgid "XY (Top)"
msgstr ""
#: xml_file_content.cpp:72
-msgid "XZ"
+msgid "YZ"
msgstr ""
#: xml_file_content.cpp:73
-msgid "&XY 100%"
+msgid "XZ"
msgstr ""
#: xml_file_content.cpp:74
-msgid "&XY Zoom In"
+msgid "&XY 100%"
msgstr ""
#: xml_file_content.cpp:75
-msgid "&XY Zoom Out"
+msgid "&XY Zoom In"
msgstr ""
#: xml_file_content.cpp:76
-msgid "Show"
+msgid "&XY Zoom Out"
msgstr ""
#: xml_file_content.cpp:77
-msgid "Show &Angles"
+msgid "Show"
msgstr ""
#: xml_file_content.cpp:78
+msgid "Show &Angles"
+msgstr ""
+
+#: xml_file_content.cpp:79
msgid "Show &Names"
msgstr ""
-#: xml_file_content.cpp:80
+#: xml_file_content.cpp:81
msgid "Show C&oordinates"
msgstr ""
-#: xml_file_content.cpp:84
+#: xml_file_content.cpp:85
msgid "Show size info"
msgstr ""
-#: xml_file_content.cpp:85
+#: xml_file_content.cpp:86
msgid "Hide/Show"
msgstr ""
-#: xml_file_content.cpp:86
+#: xml_file_content.cpp:87
msgid "Hide Selected"
msgstr ""
-#: xml_file_content.cpp:87
+#: xml_file_content.cpp:88
msgid "Hide Deselected"
msgstr ""
-#: xml_file_content.cpp:88
+#: xml_file_content.cpp:89
msgid "Show hidden"
msgstr ""
-#: xml_file_content.cpp:90
+#: xml_file_content.cpp:91
msgid "&Switch off"
msgstr ""
-#: xml_file_content.cpp:91
+#: xml_file_content.cpp:92
msgid "Set from &XY view"
msgstr ""
-#: xml_file_content.cpp:92
+#: xml_file_content.cpp:93
msgid "Set from &Brush"
msgstr ""
-#: xml_file_content.cpp:93
+#: xml_file_content.cpp:94
msgid "Set from Se&lection"
msgstr ""
-#: xml_file_content.cpp:94
+#: xml_file_content.cpp:95
msgid "Colours..."
msgstr ""
-#: xml_file_content.cpp:95
+#: xml_file_content.cpp:96
msgid "Background Image..."
msgstr ""
-#: xml_file_content.cpp:96
+#: xml_file_content.cpp:97
msgid "Mo&dify"
msgstr ""
-#: xml_file_content.cpp:97 xml_file_content.cpp:16
+#: xml_file_content.cpp:98 xml_file_content.cpp:16
msgid "Components"
msgstr ""
-#: xml_file_content.cpp:98
+#: xml_file_content.cpp:99
msgid "&Edges"
msgstr ""
-#: xml_file_content.cpp:99
+#: xml_file_content.cpp:100
msgid "&Vertices"
msgstr ""
-#: xml_file_content.cpp:100
+#: xml_file_content.cpp:101
msgid "&Faces"
msgstr ""
-#: xml_file_content.cpp:101
+#: xml_file_content.cpp:102
msgid "En&tities"
msgstr ""
-#: xml_file_content.cpp:102
+#: xml_file_content.cpp:103
msgid "Nudge"
msgstr ""
-#: xml_file_content.cpp:103
+#: xml_file_content.cpp:104
msgid "Nudge Left"
msgstr ""
-#: xml_file_content.cpp:104
+#: xml_file_content.cpp:105
msgid "Nudge Right"
msgstr ""
-#: xml_file_content.cpp:105
+#: xml_file_content.cpp:106
msgid "Nudge Up"
msgstr ""
-#: xml_file_content.cpp:106
+#: xml_file_content.cpp:107
msgid "Nudge Down"
msgstr ""
-#: xml_file_content.cpp:107 xml_file_content.cpp:15
+#: xml_file_content.cpp:108 xml_file_content.cpp:15
msgid "Rotate"
msgstr ""
-#: xml_file_content.cpp:108
+#: xml_file_content.cpp:109
msgid "Rotate X"
msgstr ""
-#: xml_file_content.cpp:109
+#: xml_file_content.cpp:110
msgid "Rotate Y"
msgstr ""
-#: xml_file_content.cpp:110
+#: xml_file_content.cpp:111
msgid "Rotate Z"
msgstr ""
-#: xml_file_content.cpp:111
+#: xml_file_content.cpp:112
msgid "Mirror"
msgstr ""
-#: xml_file_content.cpp:112
+#: xml_file_content.cpp:113
msgid "Mirror &X"
msgstr ""
-#: xml_file_content.cpp:113
+#: xml_file_content.cpp:114
msgid "Mirror &Y"
msgstr ""
-#: xml_file_content.cpp:114
+#: xml_file_content.cpp:115
msgid "Mirror &Z"
msgstr ""
-#: xml_file_content.cpp:115 xml_file_content.cpp:10
+#: xml_file_content.cpp:116 xml_file_content.cpp:10
msgid "Rotate Objects independently"
msgstr ""
-#: xml_file_content.cpp:116
+#: xml_file_content.cpp:117
msgid "Rotate and scale..."
msgstr ""
-#: xml_file_content.cpp:117
+#: xml_file_content.cpp:118
msgid "&Grid"
msgstr ""
-#: xml_file_content.cpp:118
+#: xml_file_content.cpp:119
msgid "Snap selected to grid"
msgstr ""
-#: xml_file_content.cpp:119
+#: xml_file_content.cpp:120
msgid "Grid0.125"
msgstr ""
-#: xml_file_content.cpp:120
+#: xml_file_content.cpp:121
msgid "Grid0.25"
msgstr ""
-#: xml_file_content.cpp:121
+#: xml_file_content.cpp:122
msgid "Grid0.5"
msgstr ""
-#: xml_file_content.cpp:122
+#: xml_file_content.cpp:123
msgid "Grid1"
msgstr ""
-#: xml_file_content.cpp:123
+#: xml_file_content.cpp:124
msgid "Grid2"
msgstr ""
-#: xml_file_content.cpp:124
+#: xml_file_content.cpp:125
msgid "Grid4"
msgstr ""
-#: xml_file_content.cpp:125
+#: xml_file_content.cpp:126
msgid "Grid8"
msgstr ""
-#: xml_file_content.cpp:126
+#: xml_file_content.cpp:127
msgid "Grid16"
msgstr ""
-#: xml_file_content.cpp:127
+#: xml_file_content.cpp:128
msgid "Grid32"
msgstr ""
-#: xml_file_content.cpp:128
+#: xml_file_content.cpp:129
msgid "Grid64"
msgstr ""
-#: xml_file_content.cpp:129
+#: xml_file_content.cpp:130
msgid "Grid128"
msgstr ""
-#: xml_file_content.cpp:130
+#: xml_file_content.cpp:131
msgid "Grid256"
msgstr ""
-#: xml_file_content.cpp:131
+#: xml_file_content.cpp:132
msgid "M&ap"
msgstr ""
-#: xml_file_content.cpp:132
+#: xml_file_content.cpp:133
msgid "Find brush..."
msgstr ""
-#: xml_file_content.cpp:133
+#: xml_file_content.cpp:134
msgid "Find and replace textures..."
msgstr ""
-#: xml_file_content.cpp:134
+#: xml_file_content.cpp:135
msgid "Map info..."
msgstr ""
-#: xml_file_content.cpp:135
+#: xml_file_content.cpp:136
msgid "E&ntity"
msgstr ""
-#: xml_file_content.cpp:136
+#: xml_file_content.cpp:137
msgid "&Revert group to worldspawn"
msgstr ""
-#: xml_file_content.cpp:137
+#: xml_file_content.cpp:138
msgid "&Connect selected entities"
msgstr ""
-#: xml_file_content.cpp:138
+#: xml_file_content.cpp:139
msgid "&Bind selected entities"
msgstr ""
-#: xml_file_content.cpp:140
+#: xml_file_content.cpp:141
msgid "B&rush"
msgstr ""
-#: xml_file_content.cpp:141
+#: xml_file_content.cpp:142
msgid "Prism..."
msgstr ""
-#: xml_file_content.cpp:142
+#: xml_file_content.cpp:143
msgid "Cone..."
msgstr ""
-#: xml_file_content.cpp:143
+#: xml_file_content.cpp:144
msgid "Sphere..."
msgstr ""
-#: xml_file_content.cpp:144
+#: xml_file_content.cpp:145
msgid "CSG"
msgstr ""
-#: xml_file_content.cpp:145
+#: xml_file_content.cpp:146
msgid "Make &Hollow"
msgstr ""
-#: xml_file_content.cpp:146
+#: xml_file_content.cpp:147
msgid "Make &Room"
msgstr ""
-#: xml_file_content.cpp:147
+#: xml_file_content.cpp:148
msgid "CSG &Subtract"
msgstr ""
-#: xml_file_content.cpp:148
+#: xml_file_content.cpp:149
msgid "CSG &Merge"
msgstr ""
-#: xml_file_content.cpp:150
+#: xml_file_content.cpp:151
msgid "Clip Selection"
msgstr ""
-#: xml_file_content.cpp:151
+#: xml_file_content.cpp:152
msgid "Split Selection"
msgstr ""
-#: xml_file_content.cpp:152
+#: xml_file_content.cpp:153
msgid "Flip Clip Orientation"
msgstr ""
-#: xml_file_content.cpp:153
+#: xml_file_content.cpp:154
msgid "Texture lock"
msgstr ""
-#: xml_file_content.cpp:154
+#: xml_file_content.cpp:155
msgid "Create Decal Patches"
msgstr ""
-#: xml_file_content.cpp:156
+#: xml_file_content.cpp:157
msgid "Make Detail"
msgstr ""
-#: xml_file_content.cpp:157
+#: xml_file_content.cpp:158
msgid "Make Structural"
msgstr ""
-#: xml_file_content.cpp:158
+#: xml_file_content.cpp:159
msgid "&Patch"
msgstr ""
-#: xml_file_content.cpp:159
+#: xml_file_content.cpp:160
msgid "Create Simple Patch Mesh"
msgstr ""
-#: xml_file_content.cpp:160
+#: xml_file_content.cpp:161
msgid "Create End cap"
msgstr ""
-#: xml_file_content.cpp:161
+#: xml_file_content.cpp:162
msgid "Create Bevel"
msgstr ""
-#: xml_file_content.cpp:162
+#: xml_file_content.cpp:163
msgid "Create Cone"
msgstr ""
-#: xml_file_content.cpp:163
+#: xml_file_content.cpp:164
msgid "Create Cylinder"
msgstr ""
-#: xml_file_content.cpp:164
+#: xml_file_content.cpp:165
msgid "Create Sphere"
msgstr ""
-#: xml_file_content.cpp:165
+#: xml_file_content.cpp:166
msgid "More cylinders"
msgstr ""
-#: xml_file_content.cpp:166
+#: xml_file_content.cpp:167
msgid "Create Dense Cylinder"
msgstr ""
-#: xml_file_content.cpp:167
+#: xml_file_content.cpp:168
msgid "Create Very Dense Cylinder"
msgstr ""
-#: xml_file_content.cpp:168
+#: xml_file_content.cpp:169
msgid "Create Square Cylinder"
msgstr ""
-#: xml_file_content.cpp:169
+#: xml_file_content.cpp:170
msgid "Insert"
msgstr ""
-#: xml_file_content.cpp:170
+#: xml_file_content.cpp:171
msgid "Insert 2 Columns at the beginning"
msgstr ""
-#: xml_file_content.cpp:171
+#: xml_file_content.cpp:172
msgid "Insert 2 Columns at the end"
msgstr ""
-#: xml_file_content.cpp:172
+#: xml_file_content.cpp:173
msgid "Insert 2 Rows at the beginning"
msgstr ""
-#: xml_file_content.cpp:173
+#: xml_file_content.cpp:174
msgid "Insert 2 Rows at the end"
msgstr ""
-#: xml_file_content.cpp:174
+#: xml_file_content.cpp:175
msgid "Append"
msgstr ""
-#: xml_file_content.cpp:175
+#: xml_file_content.cpp:176
msgid "Append 2 columns at the beginning"
msgstr ""
-#: xml_file_content.cpp:176
+#: xml_file_content.cpp:177
msgid "Append 2 columns at the end"
msgstr ""
-#: xml_file_content.cpp:177
+#: xml_file_content.cpp:178
msgid "Append 2 rows at the beginning"
msgstr ""
-#: xml_file_content.cpp:178
+#: xml_file_content.cpp:179
msgid "Append 2 rows at the end"
msgstr ""
-#: xml_file_content.cpp:180
-msgid "Delete 2 columns from the beginning"
-msgstr ""
-
#: xml_file_content.cpp:181
-msgid "Delete 2 columns from the end"
+msgid "Delete 2 columns from the beginning"
msgstr ""
#: xml_file_content.cpp:182
-msgid "Delete 2 rows from the beginning"
+msgid "Delete 2 columns from the end"
msgstr ""
#: xml_file_content.cpp:183
-msgid "Delete 2 rows from the end"
+msgid "Delete 2 rows from the beginning"
msgstr ""
#: xml_file_content.cpp:184
-msgid "Matrix"
+msgid "Delete 2 rows from the end"
msgstr ""
#: xml_file_content.cpp:185
-msgid "Invert"
+msgid "Matrix"
msgstr ""
#: xml_file_content.cpp:186
-msgid "Re-disperse"
+msgid "Invert"
msgstr ""
#: xml_file_content.cpp:187
-msgid "Rows"
+msgid "Re-disperse"
msgstr ""
#: xml_file_content.cpp:188
-msgid "Columns"
+msgid "Rows"
msgstr ""
#: xml_file_content.cpp:189
-msgid "Transpose"
+msgid "Columns"
msgstr ""
#: xml_file_content.cpp:190
-msgid "Thicken Selected Patches"
+msgid "Transpose"
msgstr ""
#: xml_file_content.cpp:191
-msgid "Cap Selection"
+msgid "Thicken Selected Patches"
msgstr ""
#: xml_file_content.cpp:192
-msgid "Cycle Cap Texture"
+msgid "Cap Selection"
msgstr ""
#: xml_file_content.cpp:193
@@ -5391,58 +5486,66 @@ msgid "Make Room"
msgstr ""
#: xml_file_content.cpp:20
-msgid "Put caps on the current patch"
+msgid "Group selected items"
msgstr ""
#: xml_file_content.cpp:21
-msgid "Creates a NURBS curve"
+msgid "Ungroup selected items"
msgstr ""
#: xml_file_content.cpp:22
-msgid "Convert the selected curve (NURBS <-> CatmullRom)"
+msgid "Put caps on the current patch"
msgstr ""
#: xml_file_content.cpp:23
-msgid "Appends a control point to the selected curves"
+msgid "Creates a NURBS curve"
msgstr ""
#: xml_file_content.cpp:24
-msgid "Inserts a curve control point before the selected ones"
+msgid "Convert the selected curve (NURBS <-> CatmullRom)"
msgstr ""
#: xml_file_content.cpp:25
-msgid "Removes the selected curve control points"
+msgid "Appends a control point to the selected curves"
+msgstr ""
+
+#: xml_file_content.cpp:26
+msgid "Inserts a curve control point before the selected ones"
msgstr ""
#: xml_file_content.cpp:27
+msgid "Removes the selected curve control points"
+msgstr ""
+
+#: xml_file_content.cpp:29
msgid "Find & Replace"
msgstr ""
-#: xml_file_content.cpp:28
+#: xml_file_content.cpp:30
msgid "Decrease Grid Size"
msgstr ""
-#: xml_file_content.cpp:29
+#: xml_file_content.cpp:31
msgid "Increase Grid Size"
msgstr ""
-#: xml_file_content.cpp:30
+#: xml_file_content.cpp:32
msgid "Snap to Grid"
msgstr ""
-#: xml_file_content.cpp:31
+#: xml_file_content.cpp:33
msgid "Merge Selection"
msgstr ""
-#: xml_file_content.cpp:32
+#: xml_file_content.cpp:34
msgid "Flip Selection Horiz (S-Axis)"
msgstr ""
-#: xml_file_content.cpp:33
+#: xml_file_content.cpp:35
msgid "Flip Selection Vertical (T-Axis)"
msgstr ""
-#: xml_file_content.cpp:34
+#: xml_file_content.cpp:36
msgid "Select Related Items"
msgstr ""
diff --git a/tools/innosetup/create_installer.x64.cmd b/tools/innosetup/create_installer.x64.cmd
deleted file mode 100644
index fbe43aa..0000000
--- a/tools/innosetup/create_installer.x64.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
- at echo For this script to run, please make sure that InnoSetup's compil32 is found via the PATH environment variable
-compil32 /cc darkradiant.x64.iss
\ No newline at end of file
diff --git a/tools/innosetup/create_installer.x86.cmd b/tools/innosetup/create_installer.x86.cmd
deleted file mode 100644
index 8197c77..0000000
--- a/tools/innosetup/create_installer.x86.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
- at echo For this script to run, please make sure that InnoSetup's compil32 is found via the PATH environment variable
-compil32 /cc darkradiant.iss
\ No newline at end of file
diff --git a/tools/innosetup/darkradiant.iss b/tools/innosetup/darkradiant.iss
index c3d4d83..7fd4a9c 100644
--- a/tools/innosetup/darkradiant.iss
+++ b/tools/innosetup/darkradiant.iss
@@ -3,15 +3,15 @@
[Setup]
AppName=DarkRadiant
-AppVerName=DarkRadiant 2.0.4 x86
+AppVerName=DarkRadiant 2.1.0 x86
AppPublisher=The Dark Mod
AppPublisherURL=http://www.thedarkmod.com
AppSupportURL=http://www.thedarkmod.com
AppUpdatesURL=http://www.thedarkmod.com
DefaultDirName={pf}\DarkRadiant
-DefaultGroupName=DarkRadiant 2.0.4 x86
+DefaultGroupName=DarkRadiant 2.1.0 x86
OutputDir=.
-OutputBaseFilename=darkradiant-2.0.4-x86
+OutputBaseFilename=darkradiant-2.1.0-x86
Compression=lzma
SolidCompression=yes
;ArchitecturesAllowed=x64
@@ -25,7 +25,10 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
[Files]
Source: "..\..\install\darkradiant.exe"; DestDir: "{app}"; Flags: ignoreversion
-Source: "..\..\install\*"; Excludes: "*.pdb,*.exp,*.lib,*.in,*.fbp"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "..\..\install\*"; Excludes: "*.pdb,*.exp,*.lib,*.in,*.fbp,*.iobj,*.ipdb"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT\msvcp140.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.CRT\vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion
+
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
diff --git a/tools/innosetup/darkradiant.x64.iss b/tools/innosetup/darkradiant.x64.iss
index 972bcc8..bcc931e 100644
--- a/tools/innosetup/darkradiant.x64.iss
+++ b/tools/innosetup/darkradiant.x64.iss
@@ -3,15 +3,15 @@
[Setup]
AppName=DarkRadiant
-AppVerName=DarkRadiant 2.0.4 x64
+AppVerName=DarkRadiant 2.1.0 x64
AppPublisher=The Dark Mod
AppPublisherURL=http://www.thedarkmod.com
AppSupportURL=http://www.thedarkmod.com
AppUpdatesURL=http://www.thedarkmod.com
DefaultDirName={pf}\DarkRadiant
-DefaultGroupName=DarkRadiant 2.0.4 x64
+DefaultGroupName=DarkRadiant 2.1.0 x64
OutputDir=.
-OutputBaseFilename=darkradiant-2.0.4-x64
+OutputBaseFilename=darkradiant-2.1.0-x64
Compression=lzma
SolidCompression=yes
ArchitecturesAllowed=x64
@@ -25,7 +25,9 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
[Files]
Source: "..\..\install\darkradiant.exe"; DestDir: "{app}"; Flags: ignoreversion
-Source: "..\..\install\*"; Excludes: "*.pdb,*.exp,*.lib,*.in,*.fbp"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "..\..\install\*"; Excludes: "*.pdb,*.exp,*.lib,*.in,*.fbp,*.iobj,*.ipdb"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT\msvcp140.dll"; DestDir: "{app}"; Flags: ignoreversion
+Source: "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT\vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
diff --git a/tools/msvc2013/DarkRadiant.sln b/tools/msvc2015/DarkRadiant.sln
similarity index 100%
rename from tools/msvc2013/DarkRadiant.sln
rename to tools/msvc2015/DarkRadiant.sln
diff --git a/tools/msvc2013/DarkRadiant.vcxproj b/tools/msvc2015/DarkRadiant.vcxproj
similarity index 95%
rename from tools/msvc2013/DarkRadiant.vcxproj
rename to tools/msvc2015/DarkRadiant.vcxproj
index 2186f97..65c0468 100644
--- a/tools/msvc2013/DarkRadiant.vcxproj
+++ b/tools/msvc2015/DarkRadiant.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>false</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -115,7 +115,7 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
- <AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(SolutionDir)/../../radiant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -171,7 +171,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
- <AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200 %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(SolutionDir)/../../radiant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -223,7 +223,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
- <AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200 %(AdditionalOptions)</AdditionalOptions>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
@@ -278,7 +278,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
- <AdditionalOptions>/EHsc %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200 %(AdditionalOptions)</AdditionalOptions>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
@@ -333,13 +333,17 @@
<ItemGroup>
<ClCompile Include="..\..\radiant\brush\TextureMatrix.cpp" />
<ClCompile Include="..\..\radiant\camera\CamRenderer.cpp" />
+ <ClCompile Include="..\..\radiant\layers\LayerInfoFileModule.cpp" />
<ClCompile Include="..\..\radiant\main.cpp" />
+ <ClCompile Include="..\..\radiant\map\AasFileManager.cpp" />
<ClCompile Include="..\..\radiant\map\algorithm\ChildPrimitives.cpp" />
- <ClCompile Include="..\..\radiant\map\algorithm\InfoFileExporter.cpp" />
<ClCompile Include="..\..\radiant\map\algorithm\MapExporter.cpp" />
<ClCompile Include="..\..\radiant\map\algorithm\MapImporter.cpp" />
<ClCompile Include="..\..\radiant\map\algorithm\Skins.cpp" />
- <ClCompile Include="..\..\radiant\map\InfoFile.cpp" />
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFile.cpp" />
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFileExporter.cpp" />
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFileManager.cpp" />
+ <ClCompile Include="..\..\radiant\map\RenderableAasFile.cpp" />
<ClCompile Include="..\..\radiant\namespace\ComplexName.cpp" />
<ClCompile Include="..\..\radiant\patch\algorithm\General.cpp" />
<ClCompile Include="..\..\radiant\patch\algorithm\Prefab.cpp" />
@@ -362,9 +366,15 @@
<ClCompile Include="..\..\radiant\render\View.cpp" />
<ClCompile Include="..\..\radiant\selection\algorithm\Patch.cpp" />
<ClCompile Include="..\..\radiant\selection\clipboard\Clipboard.cpp" />
+ <ClCompile Include="..\..\radiant\selection\group\SelectionGroupInfoFileModule.cpp" />
+ <ClCompile Include="..\..\radiant\selection\group\SelectionGroupManager.cpp" />
<ClCompile Include="..\..\radiant\selection\ManipulateMouseTool.cpp" />
<ClCompile Include="..\..\radiant\selection\SelectionMouseTools.cpp" />
+ <ClCompile Include="..\..\radiant\selection\selectionset\SelectionSetInfoFileModule.cpp" />
<ClCompile Include="..\..\radiant\selection\shaderclipboard\ClosestTexturableFinder.cpp" />
+ <ClCompile Include="..\..\radiant\settings\PreferencePage.cpp" />
+ <ClCompile Include="..\..\radiant\ui\aas\AasControl.cpp" />
+ <ClCompile Include="..\..\radiant\ui\aas\AasControlDialog.cpp" />
<ClCompile Include="..\..\radiant\ui\animationpreview\AnimationPreview.cpp" />
<ClCompile Include="..\..\radiant\ui\animationpreview\MD5AnimationViewer.cpp" />
<ClCompile Include="..\..\radiant\ui\mainframe\TopLevelFrame.cpp" />
@@ -412,7 +422,6 @@
<ClCompile Include="..\..\radiant\namespace\Namespace.cpp" />
<ClCompile Include="..\..\radiant\namespace\NamespaceFactory.cpp" />
<ClCompile Include="..\..\radiant\patch\Patch.cpp" />
- <ClCompile Include="..\..\radiant\patch\PatchBezier.cpp" />
<ClCompile Include="..\..\radiant\patch\PatchModule.cpp" />
<ClCompile Include="..\..\radiant\patch\PatchNode.cpp" />
<ClCompile Include="..\..\radiant\patch\PatchRenderables.cpp" />
@@ -524,6 +533,7 @@
<ClCompile Include="..\..\radiant\ui\prefabselector\PrefabPopulator.cpp" />
<ClCompile Include="..\..\radiant\ui\prefabselector\PrefabSelector.cpp" />
<ClCompile Include="..\..\radiant\ui\prefdialog\PrefDialog.cpp" />
+ <ClCompile Include="..\..\radiant\ui\prefdialog\PreferenceItem.cpp" />
<ClCompile Include="..\..\radiant\ui\prefdialog\PrefPage.cpp" />
<ClCompile Include="..\..\radiant\ui\texturebrowser\TextureBrowserManager.cpp" />
<ClCompile Include="..\..\radiant\ui\transform\TransformDialog.cpp" />
@@ -567,14 +577,18 @@
<ClInclude Include="..\..\radiant\camera\tools\CameraMouseToolEvent.h" />
<ClInclude Include="..\..\radiant\camera\tools\FreeMoveTool.h" />
<ClInclude Include="..\..\radiant\camera\tools\JumpToObjectTool.h" />
+ <ClInclude Include="..\..\radiant\camera\tools\PanViewTool.h" />
<ClInclude Include="..\..\radiant\camera\tools\ShaderClipboardTools.h" />
+ <ClInclude Include="..\..\radiant\layers\LayerInfoFileModule.h" />
+ <ClInclude Include="..\..\radiant\map\AasFileManager.h" />
<ClInclude Include="..\..\radiant\map\algorithm\ChildPrimitives.h" />
- <ClInclude Include="..\..\radiant\map\algorithm\AssignLayerMappingWalker.h" />
- <ClInclude Include="..\..\radiant\map\algorithm\InfoFileExporter.h" />
<ClInclude Include="..\..\radiant\map\algorithm\MapExporter.h" />
<ClInclude Include="..\..\radiant\map\algorithm\MapImporter.h" />
<ClInclude Include="..\..\radiant\map\algorithm\Skins.h" />
- <ClInclude Include="..\..\radiant\map\InfoFile.h" />
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFile.h" />
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFileExporter.h" />
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFileManager.h" />
+ <ClInclude Include="..\..\radiant\map\RenderableAasFile.h" />
<ClInclude Include="..\..\radiant\patch\algorithm\General.h" />
<ClInclude Include="..\..\radiant\patch\algorithm\Prefab.h" />
<ClInclude Include="..\..\radiant\precompiled.h" />
@@ -584,14 +598,24 @@
<ClInclude Include="..\..\radiant\render\backend\OpenGLStateManager.h" />
<ClInclude Include="..\..\radiant\render\frontend\RenderableCollectionWalker.h" />
<ClInclude Include="..\..\radiant\render\View.h" />
+ <ClInclude Include="..\..\radiant\selection\algorithm\CommandNotAvailableException.h" />
<ClInclude Include="..\..\radiant\selection\algorithm\Patch.h" />
<ClInclude Include="..\..\radiant\selection\BasicSelectable.h" />
<ClInclude Include="..\..\radiant\selection\clipboard\Clipboard.h" />
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroup.h" />
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroupInfoFileModule.h" />
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroupManager.h" />
<ClInclude Include="..\..\radiant\selection\ManipulateMouseTool.h" />
<ClInclude Include="..\..\radiant\selection\OccludeSelector.h" />
<ClInclude Include="..\..\radiant\selection\Rectangle.h" />
<ClInclude Include="..\..\radiant\selection\SelectionMouseTools.h" />
+ <ClInclude Include="..\..\radiant\selection\selectionset\SelectionSetInfoFileModule.h" />
<ClInclude Include="..\..\radiant\selection\shaderclipboard\ClosestTexturableFinder.h" />
+ <ClInclude Include="..\..\radiant\settings\PreferenceItemBase.h" />
+ <ClInclude Include="..\..\radiant\settings\PreferenceItems.h" />
+ <ClInclude Include="..\..\radiant\settings\PreferencePage.h" />
+ <ClInclude Include="..\..\radiant\ui\aas\AasControl.h" />
+ <ClInclude Include="..\..\radiant\ui\aas\AasControlDialog.h" />
<ClInclude Include="..\..\radiant\ui\animationpreview\AnimationPreview.h" />
<ClInclude Include="..\..\radiant\ui\animationpreview\MD5AnimationViewer.h" />
<ClInclude Include="..\..\radiant\ui\mainframe\TopLevelFrame.h" />
@@ -630,7 +654,6 @@
<ClInclude Include="..\..\radiant\clipper\ClipPoint.h" />
<ClInclude Include="..\..\radiant\map\AutoSaver.h" />
<ClInclude Include="..\..\radiant\map\CounterManager.h" />
- <ClInclude Include="..\..\radiant\map\DeferredDraw.h" />
<ClInclude Include="..\..\radiant\map\EntityBreakdown.h" />
<ClInclude Include="..\..\radiant\map\FindMapElements.h" />
<ClInclude Include="..\..\radiant\map\Map.h" />
@@ -662,7 +685,6 @@
<ClInclude Include="..\..\radiant\namespace\NamespaceFactory.h" />
<ClInclude Include="..\..\radiant\namespace\UniqueNameSet.h" />
<ClInclude Include="..\..\radiant\patch\Patch.h" />
- <ClInclude Include="..\..\radiant\patch\PatchBezier.h" />
<ClInclude Include="..\..\radiant\patch\PatchConstants.h" />
<ClInclude Include="..\..\radiant\patch\PatchControl.h" />
<ClInclude Include="..\..\radiant\patch\PatchControlInstance.h" />
@@ -803,6 +825,7 @@
<ClInclude Include="..\..\radiant\ui\prefabselector\PrefabPopulator.h" />
<ClInclude Include="..\..\radiant\ui\prefabselector\PrefabSelector.h" />
<ClInclude Include="..\..\radiant\ui\prefdialog\PrefDialog.h" />
+ <ClInclude Include="..\..\radiant\ui\prefdialog\PreferenceItem.h" />
<ClInclude Include="..\..\radiant\ui\prefdialog\PrefPage.h" />
<ClInclude Include="..\..\radiant\ui\texturebrowser\TextureBrowserManager.h" />
<ClInclude Include="..\..\radiant\ui\transform\TransformDialog.h" />
@@ -925,6 +948,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</Xml>
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\innosetup\darkradiant.iss" />
+ <None Include="..\innosetup\darkradiant.x64.iss" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/tools/msvc2013/DarkRadiant.vcxproj.filters b/tools/msvc2015/DarkRadiant.vcxproj.filters
similarity index 94%
rename from tools/msvc2013/DarkRadiant.vcxproj.filters
rename to tools/msvc2015/DarkRadiant.vcxproj.filters
index aac7434..0d02c33 100644
--- a/tools/msvc2013/DarkRadiant.vcxproj.filters
+++ b/tools/msvc2015/DarkRadiant.vcxproj.filters
@@ -185,6 +185,18 @@
<Filter Include="src\ui\mousetool">
<UniqueIdentifier>{569de02a-1a1c-46b7-9046-49bd1c575aba}</UniqueIdentifier>
</Filter>
+ <Filter Include="innosetup">
+ <UniqueIdentifier>{cec4701a-4553-44d6-aec6-199afd8a38b3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\ui\aas">
+ <UniqueIdentifier>{320a8b8c-db98-4f20-bb92-b66812bb5a53}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\map\infofile">
+ <UniqueIdentifier>{04d7b32b-b95b-41a1-93c1-3c623749b4eb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\selection\group">
+ <UniqueIdentifier>{182783ec-2373-43f8-a310-0a3e51333300}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\radiant\main.cpp">
@@ -322,9 +334,6 @@
<ClCompile Include="..\..\radiant\patch\Patch.cpp">
<Filter>src\patch</Filter>
</ClCompile>
- <ClCompile Include="..\..\radiant\patch\PatchBezier.cpp">
- <Filter>src\patch</Filter>
- </ClCompile>
<ClCompile Include="..\..\radiant\patch\PatchModule.cpp">
<Filter>src\patch</Filter>
</ClCompile>
@@ -748,12 +757,6 @@
<ClCompile Include="..\..\radiant\map\algorithm\MapExporter.cpp">
<Filter>src\map\algorithm</Filter>
</ClCompile>
- <ClCompile Include="..\..\radiant\map\algorithm\InfoFileExporter.cpp">
- <Filter>src\map\algorithm</Filter>
- </ClCompile>
- <ClCompile Include="..\..\radiant\map\InfoFile.cpp">
- <Filter>src\map</Filter>
- </ClCompile>
<ClCompile Include="..\..\radiant\map\algorithm\ChildPrimitives.cpp">
<Filter>src\map\algorithm</Filter>
</ClCompile>
@@ -850,6 +853,45 @@
<ClCompile Include="..\..\radiant\brush\TextureMatrix.cpp">
<Filter>src\brush</Filter>
</ClCompile>
+ <ClCompile Include="..\..\radiant\settings\PreferencePage.cpp">
+ <Filter>src\settings</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\ui\prefdialog\PreferenceItem.cpp">
+ <Filter>src\ui\prefdialog</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\ui\aas\AasControl.cpp">
+ <Filter>src\ui\aas</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\ui\aas\AasControlDialog.cpp">
+ <Filter>src\ui\aas</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\map\AasFileManager.cpp">
+ <Filter>src\map</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\map\RenderableAasFile.cpp">
+ <Filter>src\map</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFileManager.cpp">
+ <Filter>src\map\infofile</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFile.cpp">
+ <Filter>src\map\infofile</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\map\infofile\InfoFileExporter.cpp">
+ <Filter>src\map\infofile</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\selection\selectionset\SelectionSetInfoFileModule.cpp">
+ <Filter>src\selection\selectionset</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\layers\LayerInfoFileModule.cpp">
+ <Filter>src\layers</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\selection\group\SelectionGroupManager.cpp">
+ <Filter>src\selection\group</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\radiant\selection\group\SelectionGroupInfoFileModule.cpp">
+ <Filter>src\selection\group</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\radiant\RadiantModule.h">
@@ -957,9 +999,6 @@
<ClInclude Include="..\..\radiant\map\CounterManager.h">
<Filter>src\map</Filter>
</ClInclude>
- <ClInclude Include="..\..\radiant\map\DeferredDraw.h">
- <Filter>src\map</Filter>
- </ClInclude>
<ClInclude Include="..\..\radiant\map\EntityBreakdown.h">
<Filter>src\map</Filter>
</ClInclude>
@@ -1053,9 +1092,6 @@
<ClInclude Include="..\..\radiant\patch\Patch.h">
<Filter>src\patch</Filter>
</ClInclude>
- <ClInclude Include="..\..\radiant\patch\PatchBezier.h">
- <Filter>src\patch</Filter>
- </ClInclude>
<ClInclude Include="..\..\radiant\patch\PatchConstants.h">
<Filter>src\patch</Filter>
</ClInclude>
@@ -1602,15 +1638,6 @@
<ClInclude Include="..\..\radiant\map\algorithm\MapExporter.h">
<Filter>src\map\algorithm</Filter>
</ClInclude>
- <ClInclude Include="..\..\radiant\map\algorithm\InfoFileExporter.h">
- <Filter>src\map\algorithm</Filter>
- </ClInclude>
- <ClInclude Include="..\..\radiant\map\InfoFile.h">
- <Filter>src\map</Filter>
- </ClInclude>
- <ClInclude Include="..\..\radiant\map\algorithm\AssignLayerMappingWalker.h">
- <Filter>src\map\algorithm</Filter>
- </ClInclude>
<ClInclude Include="..\..\radiant\map\algorithm\ChildPrimitives.h">
<Filter>src\map\algorithm</Filter>
</ClInclude>
@@ -1734,6 +1761,60 @@
<ClInclude Include="..\..\radiant\brush\TextureMatrix.h">
<Filter>src\brush</Filter>
</ClInclude>
+ <ClInclude Include="..\..\radiant\settings\PreferencePage.h">
+ <Filter>src\settings</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\settings\PreferenceItemBase.h">
+ <Filter>src\settings</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\settings\PreferenceItems.h">
+ <Filter>src\settings</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\ui\prefdialog\PreferenceItem.h">
+ <Filter>src\ui\prefdialog</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\camera\tools\PanViewTool.h">
+ <Filter>src\camera\tools</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\ui\aas\AasControl.h">
+ <Filter>src\ui\aas</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\ui\aas\AasControlDialog.h">
+ <Filter>src\ui\aas</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\map\AasFileManager.h">
+ <Filter>src\map</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\map\RenderableAasFile.h">
+ <Filter>src\map</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFileManager.h">
+ <Filter>src\map\infofile</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFile.h">
+ <Filter>src\map\infofile</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\map\infofile\InfoFileExporter.h">
+ <Filter>src\map\infofile</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\selection\selectionset\SelectionSetInfoFileModule.h">
+ <Filter>src\selection\selectionset</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\layers\LayerInfoFileModule.h">
+ <Filter>src\layers</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroup.h">
+ <Filter>src\selection\group</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroupManager.h">
+ <Filter>src\selection\group</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\selection\group\SelectionGroupInfoFileModule.h">
+ <Filter>src\selection\group</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\radiant\selection\algorithm\CommandNotAvailableException.h">
+ <Filter>src\selection\algorithm</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\radiant\darkradiant.rc" />
@@ -1758,4 +1839,12 @@
<Filter>xml</Filter>
</Xml>
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\innosetup\darkradiant.iss">
+ <Filter>innosetup</Filter>
+ </None>
+ <None Include="..\innosetup\darkradiant.x64.iss">
+ <Filter>innosetup</Filter>
+ </None>
+ </ItemGroup>
</Project>
\ No newline at end of file
diff --git a/tools/msvc2013/archivezip.vcxproj b/tools/msvc2015/archivezip.vcxproj
similarity index 98%
rename from tools/msvc2013/archivezip.vcxproj
rename to tools/msvc2015/archivezip.vcxproj
index 5205d90..cbb4ac5 100644
--- a/tools/msvc2013/archivezip.vcxproj
+++ b/tools/msvc2015/archivezip.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/archivezip.vcxproj.filters b/tools/msvc2015/archivezip.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/archivezip.vcxproj.filters
rename to tools/msvc2015/archivezip.vcxproj.filters
diff --git a/tools/msvc2013/commandsystem.vcxproj b/tools/msvc2015/commandsystem.vcxproj
similarity index 98%
rename from tools/msvc2013/commandsystem.vcxproj
rename to tools/msvc2015/commandsystem.vcxproj
index af44562..e226cff 100644
--- a/tools/msvc2013/commandsystem.vcxproj
+++ b/tools/msvc2015/commandsystem.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/commandsystem.vcxproj.filters b/tools/msvc2015/commandsystem.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/commandsystem.vcxproj.filters
rename to tools/msvc2015/commandsystem.vcxproj.filters
diff --git a/tools/msvc2013/ddslib.vcxproj b/tools/msvc2015/ddslib.vcxproj
similarity index 97%
rename from tools/msvc2013/ddslib.vcxproj
rename to tools/msvc2015/ddslib.vcxproj
index 6b7891d..f52748c 100644
--- a/tools/msvc2013/ddslib.vcxproj
+++ b/tools/msvc2015/ddslib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -25,19 +25,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.conversation.vcxproj b/tools/msvc2015/dm.conversation.vcxproj
similarity index 98%
rename from tools/msvc2013/dm.conversation.vcxproj
rename to tools/msvc2015/dm.conversation.vcxproj
index 843d0bd..5d09e1b 100644
--- a/tools/msvc2013/dm.conversation.vcxproj
+++ b/tools/msvc2015/dm.conversation.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.conversation.vcxproj.filters b/tools/msvc2015/dm.conversation.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.conversation.vcxproj.filters
rename to tools/msvc2015/dm.conversation.vcxproj.filters
diff --git a/tools/msvc2013/dm.difficulty.vcxproj b/tools/msvc2015/dm.difficulty.vcxproj
similarity index 98%
rename from tools/msvc2013/dm.difficulty.vcxproj
rename to tools/msvc2015/dm.difficulty.vcxproj
index 20e97a0..e339928 100644
--- a/tools/msvc2013/dm.difficulty.vcxproj
+++ b/tools/msvc2015/dm.difficulty.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.difficulty.vcxproj.filters b/tools/msvc2015/dm.difficulty.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.difficulty.vcxproj.filters
rename to tools/msvc2015/dm.difficulty.vcxproj.filters
diff --git a/tools/msvc2013/dm.editing.vcxproj b/tools/msvc2015/dm.editing.vcxproj
similarity index 98%
rename from tools/msvc2013/dm.editing.vcxproj
rename to tools/msvc2015/dm.editing.vcxproj
index 52bf11c..c65becf 100644
--- a/tools/msvc2013/dm.editing.vcxproj
+++ b/tools/msvc2015/dm.editing.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.editing.vcxproj.filters b/tools/msvc2015/dm.editing.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.editing.vcxproj.filters
rename to tools/msvc2015/dm.editing.vcxproj.filters
diff --git a/tools/msvc2013/dm.gui.vcxproj b/tools/msvc2015/dm.gui.vcxproj
similarity index 98%
rename from tools/msvc2013/dm.gui.vcxproj
rename to tools/msvc2015/dm.gui.vcxproj
index 60a9fae..b0edaf9 100644
--- a/tools/msvc2013/dm.gui.vcxproj
+++ b/tools/msvc2015/dm.gui.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.gui.vcxproj.filters b/tools/msvc2015/dm.gui.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.gui.vcxproj.filters
rename to tools/msvc2015/dm.gui.vcxproj.filters
diff --git a/tools/msvc2013/dm.objectives.vcxproj b/tools/msvc2015/dm.objectives.vcxproj
similarity index 99%
rename from tools/msvc2013/dm.objectives.vcxproj
rename to tools/msvc2015/dm.objectives.vcxproj
index 7e5d324..39b0416 100644
--- a/tools/msvc2013/dm.objectives.vcxproj
+++ b/tools/msvc2015/dm.objectives.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.objectives.vcxproj.filters b/tools/msvc2015/dm.objectives.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.objectives.vcxproj.filters
rename to tools/msvc2015/dm.objectives.vcxproj.filters
diff --git a/tools/msvc2013/dm.stimresponse.vcxproj b/tools/msvc2015/dm.stimresponse.vcxproj
similarity index 98%
rename from tools/msvc2013/dm.stimresponse.vcxproj
rename to tools/msvc2015/dm.stimresponse.vcxproj
index 2cf9bc4..cec9e6d 100644
--- a/tools/msvc2013/dm.stimresponse.vcxproj
+++ b/tools/msvc2015/dm.stimresponse.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/dm.stimresponse.vcxproj.filters b/tools/msvc2015/dm.stimresponse.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/dm.stimresponse.vcxproj.filters
rename to tools/msvc2015/dm.stimresponse.vcxproj.filters
diff --git a/tools/msvc2013/eclassmgr.vcxproj b/tools/msvc2015/eclassmgr.vcxproj
similarity index 98%
rename from tools/msvc2013/eclassmgr.vcxproj
rename to tools/msvc2015/eclassmgr.vcxproj
index ad32384..ff499e5 100644
--- a/tools/msvc2013/eclassmgr.vcxproj
+++ b/tools/msvc2015/eclassmgr.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/eclassmgr.vcxproj.filters b/tools/msvc2015/eclassmgr.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/eclassmgr.vcxproj.filters
rename to tools/msvc2015/eclassmgr.vcxproj.filters
diff --git a/tools/msvc2013/eclasstree.vcxproj b/tools/msvc2015/eclasstree.vcxproj
similarity index 98%
rename from tools/msvc2013/eclasstree.vcxproj
rename to tools/msvc2015/eclasstree.vcxproj
index f657e2b..56e9cb4 100644
--- a/tools/msvc2013/eclasstree.vcxproj
+++ b/tools/msvc2015/eclasstree.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/eclasstree.vcxproj.filters b/tools/msvc2015/eclasstree.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/eclasstree.vcxproj.filters
rename to tools/msvc2015/eclasstree.vcxproj.filters
diff --git a/tools/msvc2013/entity.vcxproj b/tools/msvc2015/entity.vcxproj
similarity index 98%
rename from tools/msvc2013/entity.vcxproj
rename to tools/msvc2015/entity.vcxproj
index 933596f..b812ba9 100644
--- a/tools/msvc2013/entity.vcxproj
+++ b/tools/msvc2015/entity.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -117,7 +117,7 @@
</Command>
</CustomBuildStep>
<ClCompile>
- <AdditionalOptions>/EHsc</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
@@ -169,7 +169,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
- <AdditionalOptions>/EHsc</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200</AdditionalOptions>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
@@ -217,7 +217,7 @@
</Command>
</CustomBuildStep>
<ClCompile>
- <AdditionalOptions>/EHsc</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200</AdditionalOptions>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
@@ -271,7 +271,7 @@
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
- <AdditionalOptions>/EHsc</AdditionalOptions>
+ <AdditionalOptions>/EHsc /Zm200</AdditionalOptions>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
diff --git a/tools/msvc2013/entity.vcxproj.filters b/tools/msvc2015/entity.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/entity.vcxproj.filters
rename to tools/msvc2015/entity.vcxproj.filters
diff --git a/tools/msvc2013/entitylist.vcxproj b/tools/msvc2015/entitylist.vcxproj
similarity index 98%
rename from tools/msvc2013/entitylist.vcxproj
rename to tools/msvc2015/entitylist.vcxproj
index 04c21bc..da9f2d9 100644
--- a/tools/msvc2013/entitylist.vcxproj
+++ b/tools/msvc2015/entitylist.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/entitylist.vcxproj.filters b/tools/msvc2015/entitylist.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/entitylist.vcxproj.filters
rename to tools/msvc2015/entitylist.vcxproj.filters
diff --git a/tools/msvc2013/eventmanager.vcxproj b/tools/msvc2015/eventmanager.vcxproj
similarity index 98%
rename from tools/msvc2013/eventmanager.vcxproj
rename to tools/msvc2015/eventmanager.vcxproj
index a94353b..dc84574 100644
--- a/tools/msvc2013/eventmanager.vcxproj
+++ b/tools/msvc2015/eventmanager.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/eventmanager.vcxproj.filters b/tools/msvc2015/eventmanager.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/eventmanager.vcxproj.filters
rename to tools/msvc2015/eventmanager.vcxproj.filters
diff --git a/tools/msvc2013/filetypes.vcxproj b/tools/msvc2015/filetypes.vcxproj
similarity index 98%
rename from tools/msvc2013/filetypes.vcxproj
rename to tools/msvc2015/filetypes.vcxproj
index 7065923..fda4c1c 100644
--- a/tools/msvc2013/filetypes.vcxproj
+++ b/tools/msvc2015/filetypes.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/filetypes.vcxproj.filters b/tools/msvc2015/filetypes.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/filetypes.vcxproj.filters
rename to tools/msvc2015/filetypes.vcxproj.filters
diff --git a/tools/msvc2013/filters.vcxproj b/tools/msvc2015/filters.vcxproj
similarity index 98%
rename from tools/msvc2013/filters.vcxproj
rename to tools/msvc2015/filters.vcxproj
index b4e7461..da2b340 100644
--- a/tools/msvc2013/filters.vcxproj
+++ b/tools/msvc2015/filters.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/filters.vcxproj.filters b/tools/msvc2015/filters.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/filters.vcxproj.filters
rename to tools/msvc2015/filters.vcxproj.filters
diff --git a/tools/msvc2013/fonts.vcxproj b/tools/msvc2015/fonts.vcxproj
similarity index 98%
rename from tools/msvc2013/fonts.vcxproj
rename to tools/msvc2015/fonts.vcxproj
index 56c48cd..8818bb0 100644
--- a/tools/msvc2013/fonts.vcxproj
+++ b/tools/msvc2015/fonts.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/fonts.vcxproj.filters b/tools/msvc2015/fonts.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/fonts.vcxproj.filters
rename to tools/msvc2015/fonts.vcxproj.filters
diff --git a/tools/msvc2013/grid.vcxproj b/tools/msvc2015/grid.vcxproj
similarity index 98%
rename from tools/msvc2013/grid.vcxproj
rename to tools/msvc2015/grid.vcxproj
index bb75f02..b7bf794 100644
--- a/tools/msvc2013/grid.vcxproj
+++ b/tools/msvc2015/grid.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/grid.vcxproj.filters b/tools/msvc2015/grid.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/grid.vcxproj.filters
rename to tools/msvc2015/grid.vcxproj.filters
diff --git a/tools/msvc2013/image.vcxproj b/tools/msvc2015/image.vcxproj
similarity index 98%
rename from tools/msvc2013/image.vcxproj
rename to tools/msvc2015/image.vcxproj
index 3003f8a..4b11d81 100644
--- a/tools/msvc2013/image.vcxproj
+++ b/tools/msvc2015/image.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/image.vcxproj.filters b/tools/msvc2015/image.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/image.vcxproj.filters
rename to tools/msvc2015/image.vcxproj.filters
diff --git a/tools/msvc2013/include.vcxproj b/tools/msvc2015/include.vcxproj
similarity index 92%
rename from tools/msvc2013/include.vcxproj
rename to tools/msvc2015/include.vcxproj
index f59fc06..e66df2a 100644
--- a/tools/msvc2013/include.vcxproj
+++ b/tools/msvc2015/include.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -24,19 +24,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -82,16 +82,16 @@
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\..\..\build\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(IncludePath)</IncludePath>
+ <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(W32DepsDir)\libsigc++\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(IncludePath)</IncludePath>
+ <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(W32DepsDir)\libsigc++\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(IncludePath)</IncludePath>
+ <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(W32DepsDir)\libsigc++\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(IncludePath)</IncludePath>
+ <IncludePath>$(DarkRadiantRoot)\libs;$(W32DepsDir)\boost;$(W32DepsDir)\libsigc++\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
@@ -108,6 +108,7 @@
<ClInclude Include="..\..\include\editable.h" />
<ClInclude Include="..\..\include\GLProgramAttributes.h" />
<ClInclude Include="..\..\include\i18n.h" />
+ <ClInclude Include="..\..\include\iaasfile.h" />
<ClInclude Include="..\..\include\iarchive.h" />
<ClInclude Include="..\..\include\ibrush.h" />
<ClInclude Include="..\..\include\icamera.h" />
@@ -144,6 +145,7 @@
<ClInclude Include="..\..\include\imap.h" />
<ClInclude Include="..\..\include\imapcompiler.h" />
<ClInclude Include="..\..\include\imapformat.h" />
+ <ClInclude Include="..\..\include\imapinfofile.h" />
<ClInclude Include="..\..\include\imapresource.h" />
<ClInclude Include="..\..\include\imd5anim.h" />
<ClInclude Include="..\..\include\imd5model.h" />
@@ -175,6 +177,7 @@
<ClInclude Include="..\..\include\iscenegraphfactory.h" />
<ClInclude Include="..\..\include\iscript.h" />
<ClInclude Include="..\..\include\iselectable.h" />
+ <ClInclude Include="..\..\include\iselectiongroup.h" />
<ClInclude Include="..\..\include\iselectiontest.h" />
<ClInclude Include="..\..\include\iselection.h" />
<ClInclude Include="..\..\include\iselectionset.h" />
diff --git a/tools/msvc2013/libs.vcxproj b/tools/msvc2015/libs.vcxproj
similarity index 97%
rename from tools/msvc2013/libs.vcxproj
rename to tools/msvc2015/libs.vcxproj
index b983413..f575d07 100644
--- a/tools/msvc2013/libs.vcxproj
+++ b/tools/msvc2015/libs.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -26,26 +26,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Utility</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
@@ -190,7 +190,6 @@
<ClInclude Include="..\..\libs\render\VertexNT.h" />
<ClInclude Include="..\..\libs\RGBAImage.h" />
<ClInclude Include="..\..\libs\scenelib.h" />
- <ClInclude Include="..\..\libs\SelectableNode.h" />
<ClInclude Include="..\..\libs\selectionlib.h" />
<ClInclude Include="..\..\libs\shaderlib.h" />
<ClInclude Include="..\..\libs\stream\BufferInputStream.h" />
diff --git a/tools/msvc2013/libs.vcxproj.filters b/tools/msvc2015/libs.vcxproj.filters
similarity index 99%
rename from tools/msvc2013/libs.vcxproj.filters
rename to tools/msvc2015/libs.vcxproj.filters
index de10c1a..8a19ffc 100644
--- a/tools/msvc2013/libs.vcxproj.filters
+++ b/tools/msvc2015/libs.vcxproj.filters
@@ -135,7 +135,6 @@
<ClInclude Include="..\..\libs\Transformable.h" />
<ClInclude Include="..\..\libs\BasicUndoMemento.h" />
<ClInclude Include="..\..\libs\ObservedUndoable.h" />
- <ClInclude Include="..\..\libs\SelectableNode.h" />
<ClInclude Include="..\..\libs\ObservedSelectable.h" />
<ClInclude Include="..\..\libs\stream\ScopedArchiveBuffer.h">
<Filter>stream</Filter>
diff --git a/tools/msvc2013/mapdoom3.vcxproj b/tools/msvc2015/mapdoom3.vcxproj
similarity index 96%
rename from tools/msvc2013/mapdoom3.vcxproj
rename to tools/msvc2015/mapdoom3.vcxproj
index 84cef96..2194bc6 100644
--- a/tools/msvc2013/mapdoom3.vcxproj
+++ b/tools/msvc2015/mapdoom3.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -311,6 +311,10 @@
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFile.h" />
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFileLoader.h" />
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFileSettings.h" />
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Util.h" />
<ClInclude Include="..\..\plugins\mapdoom3\compiler\BspTree.h" />
<ClInclude Include="..\..\plugins\mapdoom3\compiler\DebugRenderer.h" />
<ClInclude Include="..\..\plugins\mapdoom3\compiler\Doom3MapCompiler.h" />
@@ -346,6 +350,9 @@
<ClInclude Include="..\..\plugins\mapdoom3\primitivewriters\PatchDefExporter.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFile.cpp" />
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFileLoader.cpp" />
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFileSettings.cpp" />
<ClCompile Include="..\..\plugins\mapdoom3\compiler\Doom3MapCompiler.cpp" />
<ClCompile Include="..\..\plugins\mapdoom3\compiler\OptIsland.cpp" />
<ClCompile Include="..\..\plugins\mapdoom3\compiler\ProcCompiler.cpp" />
diff --git a/tools/msvc2013/mapdoom3.vcxproj.filters b/tools/msvc2015/mapdoom3.vcxproj.filters
similarity index 88%
rename from tools/msvc2013/mapdoom3.vcxproj.filters
rename to tools/msvc2015/mapdoom3.vcxproj.filters
index 560315c..a13e7a3 100644
--- a/tools/msvc2013/mapdoom3.vcxproj.filters
+++ b/tools/msvc2015/mapdoom3.vcxproj.filters
@@ -14,6 +14,9 @@
<Filter Include="src\compiler">
<UniqueIdentifier>{f6fd3c0c-b85a-44fd-9149-fa840615ac31}</UniqueIdentifier>
</Filter>
+ <Filter Include="src\aas">
+ <UniqueIdentifier>{48df04ae-bfe5-475d-91e7-972f10239051}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\plugins\mapdoom3\Doom3MapFormat.h">
@@ -115,6 +118,18 @@
<ClInclude Include="..\..\plugins\mapdoom3\primitivewriters\BrushDefExporter.h">
<Filter>src\primitivewriters</Filter>
</ClInclude>
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFile.h">
+ <Filter>src\aas</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFileLoader.h">
+ <Filter>src\aas</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Doom3AasFileSettings.h">
+ <Filter>src\aas</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\plugins\mapdoom3\aas\Util.h">
+ <Filter>src\aas</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\plugins\mapdoom3\Doom3MapFormat.cpp">
@@ -183,6 +198,15 @@
<ClCompile Include="..\..\plugins\mapdoom3\Quake3MapReader.cpp">
<Filter>src</Filter>
</ClCompile>
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFileLoader.cpp">
+ <Filter>src\aas</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFileSettings.cpp">
+ <Filter>src\aas</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\plugins\mapdoom3\aas\Doom3AasFile.cpp">
+ <Filter>src\aas</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\plugins\mapdoom3\mapdoom3.def">
diff --git a/tools/msvc2013/mathlib.vcxproj b/tools/msvc2015/mathlib.vcxproj
similarity index 97%
rename from tools/msvc2013/mathlib.vcxproj
rename to tools/msvc2015/mathlib.vcxproj
index 305af86..aa92ea9 100644
--- a/tools/msvc2013/mathlib.vcxproj
+++ b/tools/msvc2015/mathlib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -24,19 +24,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/md5model.vcxproj b/tools/msvc2015/md5model.vcxproj
similarity index 98%
rename from tools/msvc2013/md5model.vcxproj
rename to tools/msvc2015/md5model.vcxproj
index 1231cbc..1388ff5 100644
--- a/tools/msvc2013/md5model.vcxproj
+++ b/tools/msvc2015/md5model.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/md5model.vcxproj.filters b/tools/msvc2015/md5model.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/md5model.vcxproj.filters
rename to tools/msvc2015/md5model.vcxproj.filters
diff --git a/tools/msvc2013/model.vcxproj b/tools/msvc2015/model.vcxproj
similarity index 98%
rename from tools/msvc2013/model.vcxproj
rename to tools/msvc2015/model.vcxproj
index fe0b037..0ed5dda 100644
--- a/tools/msvc2013/model.vcxproj
+++ b/tools/msvc2015/model.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/model.vcxproj.filters b/tools/msvc2015/model.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/model.vcxproj.filters
rename to tools/msvc2015/model.vcxproj.filters
diff --git a/tools/msvc2013/particles.vcxproj b/tools/msvc2015/particles.vcxproj
similarity index 98%
rename from tools/msvc2013/particles.vcxproj
rename to tools/msvc2015/particles.vcxproj
index 48c757c..bd523b9 100644
--- a/tools/msvc2013/particles.vcxproj
+++ b/tools/msvc2015/particles.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/particles.vcxproj.filters b/tools/msvc2015/particles.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/particles.vcxproj.filters
rename to tools/msvc2015/particles.vcxproj.filters
diff --git a/tools/msvc2013/picomodellib.vcxproj b/tools/msvc2015/picomodellib.vcxproj
similarity index 97%
rename from tools/msvc2013/picomodellib.vcxproj
rename to tools/msvc2015/picomodellib.vcxproj
index 623942d..0ba0b09 100644
--- a/tools/msvc2013/picomodellib.vcxproj
+++ b/tools/msvc2015/picomodellib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -25,19 +25,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/picomodellib.vcxproj.filters b/tools/msvc2015/picomodellib.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/picomodellib.vcxproj.filters
rename to tools/msvc2015/picomodellib.vcxproj.filters
diff --git a/tools/msvc2013/post_build_event.cmd b/tools/msvc2015/post_build_event.cmd
similarity index 54%
rename from tools/msvc2013/post_build_event.cmd
rename to tools/msvc2015/post_build_event.cmd
index 2fff859..91c9d91 100644
--- a/tools/msvc2013/post_build_event.cmd
+++ b/tools/msvc2015/post_build_event.cmd
@@ -11,14 +11,14 @@ IF "%1" == "Debug" (SET WXLIB_SUFFIX=ud) ELSE (SET WXLIB_SUFFIX=u)
@echo Copying wxWidgets binaries
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_gl_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_html_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_xrc_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_stc_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxbase30%WXLIB_SUFFIX%_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxbase30%WXLIB_SUFFIX%_xml_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_adv_%2.dll ..\..\install /Y
-copy ..\..\w32deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_core_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_gl_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_html_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_xrc_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_stc_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxbase310%WXLIB_SUFFIX%_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxbase310%WXLIB_SUFFIX%_xml_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_adv_%2.dll ..\..\install /Y
+copy ..\..\w32deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_core_%2.dll ..\..\install /Y
IF "%1" == "Debug" (SET DEBUG_SUFFIX=-d) ELSE (SET DEBUG_SUFFIX=)
diff --git a/tools/msvc2013/post_build_event_x64.cmd b/tools/msvc2015/post_build_event_x64.cmd
similarity index 53%
rename from tools/msvc2013/post_build_event_x64.cmd
rename to tools/msvc2015/post_build_event_x64.cmd
index 5e28465..25c4b59 100644
--- a/tools/msvc2013/post_build_event_x64.cmd
+++ b/tools/msvc2015/post_build_event_x64.cmd
@@ -11,14 +11,14 @@ IF "%1" == "Debug" (SET WXLIB_SUFFIX=ud) ELSE (SET WXLIB_SUFFIX=u)
@echo Copying wxWidgets binaries
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_gl_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_html_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_xrc_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_stc_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxbase30%WXLIB_SUFFIX%_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxbase30%WXLIB_SUFFIX%_xml_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_adv_%2_x64.dll ..\..\install /Y
-copy ..\..\w64deps\wxWidgets\bin\wxmsw30%WXLIB_SUFFIX%_core_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_gl_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_html_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_xrc_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_stc_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxbase310%WXLIB_SUFFIX%_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxbase310%WXLIB_SUFFIX%_xml_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_adv_%2_x64.dll ..\..\install /Y
+copy ..\..\w64deps\wxWidgets\bin\wxmsw310%WXLIB_SUFFIX%_core_%2_x64.dll ..\..\install /Y
IF "%1" == "Debug" (SET DEBUG_SUFFIX=-d) ELSE (SET DEBUG_SUFFIX=)
diff --git a/tools/msvc2013/properties/Boost.props b/tools/msvc2015/properties/Boost.props
similarity index 100%
rename from tools/msvc2013/properties/Boost.props
rename to tools/msvc2015/properties/Boost.props
diff --git a/tools/msvc2013/properties/DarkRadiant Base Debug Win32.props b/tools/msvc2015/properties/DarkRadiant Base Debug Win32.props
similarity index 100%
rename from tools/msvc2013/properties/DarkRadiant Base Debug Win32.props
rename to tools/msvc2015/properties/DarkRadiant Base Debug Win32.props
diff --git a/tools/msvc2013/properties/DarkRadiant Base Debug x64.props b/tools/msvc2015/properties/DarkRadiant Base Debug x64.props
similarity index 85%
rename from tools/msvc2013/properties/DarkRadiant Base Debug x64.props
rename to tools/msvc2015/properties/DarkRadiant Base Debug x64.props
index 66d3dc1..fcba6b5 100644
--- a/tools/msvc2013/properties/DarkRadiant Base Debug x64.props
+++ b/tools/msvc2015/properties/DarkRadiant Base Debug x64.props
@@ -12,6 +12,9 @@
<ItemDefinitionGroup>
<Link />
<Link />
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<BuildMacro Include="PlatformDepsDir">
diff --git a/tools/msvc2013/properties/DarkRadiant Base Release Win32.props b/tools/msvc2015/properties/DarkRadiant Base Release Win32.props
similarity index 100%
rename from tools/msvc2013/properties/DarkRadiant Base Release Win32.props
rename to tools/msvc2015/properties/DarkRadiant Base Release Win32.props
diff --git a/tools/msvc2013/properties/DarkRadiant Base Release x64.props b/tools/msvc2015/properties/DarkRadiant Base Release x64.props
similarity index 80%
rename from tools/msvc2013/properties/DarkRadiant Base Release x64.props
rename to tools/msvc2015/properties/DarkRadiant Base Release x64.props
index 6261d9f..f2cb49d 100644
--- a/tools/msvc2013/properties/DarkRadiant Base Release x64.props
+++ b/tools/msvc2015/properties/DarkRadiant Base Release x64.props
@@ -10,7 +10,11 @@
<WxWidgetsLibDir>vc$(PlatformToolsetVersion)_x64_dll</WxWidgetsLibDir>
</PropertyGroup>
<PropertyGroup />
- <ItemDefinitionGroup />
+ <ItemDefinitionGroup>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemDefinitionGroup>
<ItemGroup>
<BuildMacro Include="PlatformDepsDir">
<Value>$(PlatformDepsDir)</Value>
diff --git a/tools/msvc2013/properties/DarkRadiant Base.props b/tools/msvc2015/properties/DarkRadiant Base.props
similarity index 100%
rename from tools/msvc2013/properties/DarkRadiant Base.props
rename to tools/msvc2015/properties/DarkRadiant Base.props
diff --git a/tools/msvc2013/properties/GLEW.props b/tools/msvc2015/properties/GLEW.props
similarity index 100%
rename from tools/msvc2013/properties/GLEW.props
rename to tools/msvc2015/properties/GLEW.props
diff --git a/tools/msvc2013/properties/OpenAL + Vorbis.props b/tools/msvc2015/properties/OpenAL + Vorbis.props
similarity index 100%
rename from tools/msvc2013/properties/OpenAL + Vorbis.props
rename to tools/msvc2015/properties/OpenAL + Vorbis.props
diff --git a/tools/msvc2013/properties/Python.props b/tools/msvc2015/properties/Python.props
similarity index 100%
rename from tools/msvc2013/properties/Python.props
rename to tools/msvc2015/properties/Python.props
diff --git a/tools/msvc2013/properties/ftgl.props b/tools/msvc2015/properties/ftgl.props
similarity index 100%
rename from tools/msvc2013/properties/ftgl.props
rename to tools/msvc2015/properties/ftgl.props
diff --git a/tools/msvc2013/properties/libpng.props b/tools/msvc2015/properties/libpng.props
similarity index 100%
rename from tools/msvc2013/properties/libpng.props
rename to tools/msvc2015/properties/libpng.props
diff --git a/tools/msvc2013/properties/libxml2.props b/tools/msvc2015/properties/libxml2.props
similarity index 100%
rename from tools/msvc2013/properties/libxml2.props
rename to tools/msvc2015/properties/libxml2.props
diff --git a/tools/msvc2013/properties/win_iconv.props b/tools/msvc2015/properties/win_iconv.props
similarity index 100%
rename from tools/msvc2013/properties/win_iconv.props
rename to tools/msvc2015/properties/win_iconv.props
diff --git a/tools/msvc2013/properties/wxWidgets.props b/tools/msvc2015/properties/wxWidgets.props
similarity index 100%
rename from tools/msvc2013/properties/wxWidgets.props
rename to tools/msvc2015/properties/wxWidgets.props
diff --git a/tools/msvc2013/properties/zlib.props b/tools/msvc2015/properties/zlib.props
similarity index 100%
rename from tools/msvc2013/properties/zlib.props
rename to tools/msvc2015/properties/zlib.props
diff --git a/tools/msvc2013/scenegraph.vcxproj b/tools/msvc2015/scenegraph.vcxproj
similarity index 98%
rename from tools/msvc2013/scenegraph.vcxproj
rename to tools/msvc2015/scenegraph.vcxproj
index 1031a53..d5fbca8 100644
--- a/tools/msvc2013/scenegraph.vcxproj
+++ b/tools/msvc2015/scenegraph.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/scenegraph.vcxproj.filters b/tools/msvc2015/scenegraph.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/scenegraph.vcxproj.filters
rename to tools/msvc2015/scenegraph.vcxproj.filters
diff --git a/tools/msvc2013/scenelib.vcxproj b/tools/msvc2015/scenelib.vcxproj
similarity index 96%
rename from tools/msvc2013/scenelib.vcxproj
rename to tools/msvc2015/scenelib.vcxproj
index 668bcb4..f41b3c0 100644
--- a/tools/msvc2013/scenelib.vcxproj
+++ b/tools/msvc2015/scenelib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -24,19 +24,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -135,6 +135,7 @@
<ItemGroup>
<ClCompile Include="..\..\libs\scene\InstanceWalkers.cpp" />
<ClCompile Include="..\..\libs\scene\Node.cpp" />
+ <ClCompile Include="..\..\libs\scene\SelectableNode.cpp" />
<ClCompile Include="..\..\libs\scene\TraversableNodeSet.cpp" />
</ItemGroup>
<ItemGroup>
@@ -142,6 +143,7 @@
<ClInclude Include="..\..\libs\scene\InstanceWalkers.h" />
<ClInclude Include="..\..\libs\scene\LayerValidityCheckWalker.h" />
<ClInclude Include="..\..\libs\scene\Node.h" />
+ <ClInclude Include="..\..\libs\scene\SelectableNode.h" />
<ClInclude Include="..\..\libs\scene\TraversableNodeSet.h" />
<ClInclude Include="..\..\libs\scenelib.h" />
<ClInclude Include="..\..\libs\selectionlib.h" />
diff --git a/tools/msvc2013/scenelib.vcxproj.filters b/tools/msvc2015/scenelib.vcxproj.filters
similarity index 85%
rename from tools/msvc2013/scenelib.vcxproj.filters
rename to tools/msvc2015/scenelib.vcxproj.filters
index c4e1f02..74bfe91 100644
--- a/tools/msvc2013/scenelib.vcxproj.filters
+++ b/tools/msvc2015/scenelib.vcxproj.filters
@@ -15,6 +15,9 @@
<ClCompile Include="..\..\libs\scene\TraversableNodeSet.cpp">
<Filter>scene</Filter>
</ClCompile>
+ <ClCompile Include="..\..\libs\scene\SelectableNode.cpp">
+ <Filter>scene</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\libs\scene\InstanceWalkers.h">
@@ -34,5 +37,8 @@
<ClInclude Include="..\..\libs\scene\BasicRootNode.h">
<Filter>scene</Filter>
</ClInclude>
+ <ClInclude Include="..\..\libs\scene\SelectableNode.h">
+ <Filter>scene</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
diff --git a/tools/msvc2013/script.vcxproj b/tools/msvc2015/script.vcxproj
similarity index 98%
rename from tools/msvc2013/script.vcxproj
rename to tools/msvc2015/script.vcxproj
index f933a15..bcc9fd7 100644
--- a/tools/msvc2013/script.vcxproj
+++ b/tools/msvc2015/script.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/script.vcxproj.filters b/tools/msvc2015/script.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/script.vcxproj.filters
rename to tools/msvc2015/script.vcxproj.filters
diff --git a/tools/msvc2013/shaders.vcxproj b/tools/msvc2015/shaders.vcxproj
similarity index 98%
rename from tools/msvc2013/shaders.vcxproj
rename to tools/msvc2015/shaders.vcxproj
index 3758966..de93b24 100644
--- a/tools/msvc2013/shaders.vcxproj
+++ b/tools/msvc2015/shaders.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/shaders.vcxproj.filters b/tools/msvc2015/shaders.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/shaders.vcxproj.filters
rename to tools/msvc2015/shaders.vcxproj.filters
diff --git a/tools/msvc2013/skins.vcxproj b/tools/msvc2015/skins.vcxproj
similarity index 98%
rename from tools/msvc2013/skins.vcxproj
rename to tools/msvc2015/skins.vcxproj
index c14dbdb..efa5572 100644
--- a/tools/msvc2013/skins.vcxproj
+++ b/tools/msvc2015/skins.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/skins.vcxproj.filters b/tools/msvc2015/skins.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/skins.vcxproj.filters
rename to tools/msvc2015/skins.vcxproj.filters
diff --git a/tools/msvc2013/sound.vcxproj b/tools/msvc2015/sound.vcxproj
similarity index 98%
rename from tools/msvc2013/sound.vcxproj
rename to tools/msvc2015/sound.vcxproj
index 3f4e527..c357dbb 100644
--- a/tools/msvc2013/sound.vcxproj
+++ b/tools/msvc2015/sound.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/sound.vcxproj.filters b/tools/msvc2015/sound.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/sound.vcxproj.filters
rename to tools/msvc2015/sound.vcxproj.filters
diff --git a/tools/msvc2013/uimanager.vcxproj b/tools/msvc2015/uimanager.vcxproj
similarity index 98%
rename from tools/msvc2013/uimanager.vcxproj
rename to tools/msvc2015/uimanager.vcxproj
index 4a4d9af..b6b8678 100644
--- a/tools/msvc2013/uimanager.vcxproj
+++ b/tools/msvc2015/uimanager.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/uimanager.vcxproj.filters b/tools/msvc2015/uimanager.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/uimanager.vcxproj.filters
rename to tools/msvc2015/uimanager.vcxproj.filters
diff --git a/tools/msvc2013/undo.vcxproj b/tools/msvc2015/undo.vcxproj
similarity index 98%
rename from tools/msvc2013/undo.vcxproj
rename to tools/msvc2015/undo.vcxproj
index 8ca8991..c0d0c59 100644
--- a/tools/msvc2013/undo.vcxproj
+++ b/tools/msvc2015/undo.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/undo.vcxproj.filters b/tools/msvc2015/undo.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/undo.vcxproj.filters
rename to tools/msvc2015/undo.vcxproj.filters
diff --git a/tools/msvc2013/vfspk3.vcxproj b/tools/msvc2015/vfspk3.vcxproj
similarity index 98%
rename from tools/msvc2013/vfspk3.vcxproj
rename to tools/msvc2015/vfspk3.vcxproj
index 01468e0..47e70b8 100644
--- a/tools/msvc2013/vfspk3.vcxproj
+++ b/tools/msvc2015/vfspk3.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/vfspk3.vcxproj.filters b/tools/msvc2015/vfspk3.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/vfspk3.vcxproj.filters
rename to tools/msvc2015/vfspk3.vcxproj.filters
diff --git a/tools/msvc2013/wavefront.vcxproj b/tools/msvc2015/wavefront.vcxproj
similarity index 100%
rename from tools/msvc2013/wavefront.vcxproj
rename to tools/msvc2015/wavefront.vcxproj
diff --git a/tools/msvc2013/wavefront.vcxproj.filters b/tools/msvc2015/wavefront.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/wavefront.vcxproj.filters
rename to tools/msvc2015/wavefront.vcxproj.filters
diff --git a/tools/msvc2013/wxutillib.vcxproj b/tools/msvc2015/wxutillib.vcxproj
similarity index 98%
rename from tools/msvc2013/wxutillib.vcxproj
rename to tools/msvc2015/wxutillib.vcxproj
index de3f7d5..f0996f7 100644
--- a/tools/msvc2013/wxutillib.vcxproj
+++ b/tools/msvc2015/wxutillib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -26,22 +26,22 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
diff --git a/tools/msvc2013/wxutillib.vcxproj.filters b/tools/msvc2015/wxutillib.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/wxutillib.vcxproj.filters
rename to tools/msvc2015/wxutillib.vcxproj.filters
diff --git a/tools/msvc2013/xmlregistry.vcxproj b/tools/msvc2015/xmlregistry.vcxproj
similarity index 98%
rename from tools/msvc2013/xmlregistry.vcxproj
rename to tools/msvc2015/xmlregistry.vcxproj
index dd1324f..d7d701d 100644
--- a/tools/msvc2013/xmlregistry.vcxproj
+++ b/tools/msvc2015/xmlregistry.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -28,23 +28,23 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/msvc2013/xmlregistry.vcxproj.filters b/tools/msvc2015/xmlregistry.vcxproj.filters
similarity index 100%
rename from tools/msvc2013/xmlregistry.vcxproj.filters
rename to tools/msvc2015/xmlregistry.vcxproj.filters
diff --git a/tools/msvc2013/xmlutillib.vcxproj b/tools/msvc2015/xmlutillib.vcxproj
similarity index 97%
rename from tools/msvc2013/xmlutillib.vcxproj
rename to tools/msvc2015/xmlutillib.vcxproj
index 60dd6e2..f9026c9 100644
--- a/tools/msvc2013/xmlutillib.vcxproj
+++ b/tools/msvc2015/xmlutillib.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -25,19 +25,19 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
- <PlatformToolset>v120</PlatformToolset>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/tools/scripts/build_boost_libs.cmd b/tools/scripts/build_boost_libs.cmd
index 317c709..71b0761 100644
--- a/tools/scripts/build_boost_libs.cmd
+++ b/tools/scripts/build_boost_libs.cmd
@@ -4,45 +4,22 @@ rem Launch this file in the boost/ folder.
rem Check if we're in the correct folder
if not exist libs goto :error
if not exist boost goto :error
+if not exist b2.exe goto :error
mkdir stage
-cd libs\filesystem\build
-bjam --toolset=msvc link=static threading=multi release stage
-bjam --toolset=msvc link=static threading=multi debug stage
-copy stage\*.lib ..\..\..\stage
+b2 toolset=msvc variant=release,debug link=static threading=multi stage /boost/python /boost/filesystem /boost/regex /boost/system
-cd ..\..\..\libs\system\build
-bjam --toolset=msvc link=static threading=multi release stage
-bjam --toolset=msvc link=static threading=multi debug stage
-copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\libs\python\build
-bjam --toolset=msvc link=static threading=multi release stage
-bjam --toolset=msvc link=static threading=multi debug stage
-copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\libs\regex\build
-bjam --toolset=msvc link=static threading=multi release stage
-bjam --toolset=msvc link=static threading=multi debug stage
-copy stage\*.lib ..\..\..\stage
-
-rem cd ..\..\..\libs\signals\build
-rem bjam --toolset=msvc link=static threading=multi release stage
-rem bjam --toolset=msvc link=static threading=multi debug stage
-rem copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\stage
-start .
+start stage
goto :success
:error
echo Please launch this file in the boost folder you downloaded and extracted from sourceforge.
-echo Note that you need to have the path to bjam.exe in your PATH environment variable.
-echo
+echo Run the bootstrap.bat file to generate the b2.exe file needed for the build process.
+echo __________________________________________________________________________________________
echo Example:
-echo cd c:\Downloads\boost_1_55_0\
+echo cd c:\Downloads\boost_1_61_0\
echo c:\Games\DarkRadiant\tools\scripts\build_boost_libs.cmd
goto :eof
diff --git a/tools/scripts/build_boost_libs.x64.cmd b/tools/scripts/build_boost_libs.x64.cmd
index 2935536..50acc81 100644
--- a/tools/scripts/build_boost_libs.x64.cmd
+++ b/tools/scripts/build_boost_libs.x64.cmd
@@ -4,46 +4,23 @@ rem Launch this file in the boost/ folder.
rem Check if we're in the correct folder
if not exist libs goto :error
if not exist boost goto :error
+if not exist b2.exe goto :error
mkdir stage
-cd libs\filesystem\build
-bjam --toolset=msvc address-model=64 threading=multi link=static release stage
-bjam --toolset=msvc address-model=64 threading=multi link=static debug stage
-copy stage\*.lib ..\..\..\stage
+b2 toolset=msvc variant=release,debug link=static threading=multi address-model=64 stage /boost/python /boost/filesystem /boost/regex /boost/system
-cd ..\..\..\libs\system\build
-bjam --toolset=msvc address-model=64 threading=multi link=static release stage
-bjam --toolset=msvc address-model=64 threading=multi link=static debug stage
-copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\libs\python\build
-bjam --toolset=msvc address-model=64 threading=multi link=static release stage
-bjam --toolset=msvc address-model=64 threading=multi link=static debug stage
-copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\libs\regex\build
-bjam --toolset=msvc address-model=64 threading=multi link=static release stage
-bjam --toolset=msvc address-model=64 threading=multi link=static debug stage
-copy stage\*.lib ..\..\..\stage
-
-rem cd ..\..\..\libs\signals\build
-rem bjam --toolset=msvc address-model=64 threading=multi link=static release stage
-rem bjam --toolset=msvc address-model=64 threading=multi link=static debug stage
-rem copy stage\*.lib ..\..\..\stage
-
-cd ..\..\..\stage
-start .
+start stage
goto :success
:error
echo Please launch this file in the boost folder you downloaded and extracted from sourceforge.
-echo Note that you need to have the path to bjam.exe in your PATH environment variable.
+echo Run the bootstrap.bat file to generate the b2.exe file needed for the build process.
echo __________________________________________________________________________________________
echo Example:
-echo cd c:\Downloads\boost_1_55_0\
-echo c:\Games\DarkRadiant\tools\scripts\build_boost_libs.cmd
+echo cd c:\Downloads\boost_1_61_0\
+echo c:\Games\DarkRadiant\tools\scripts\build_boost_libs.x64.cmd
goto :eof
:success
diff --git a/tools/scripts/compile_release_package.ps1 b/tools/scripts/compile_release_package.ps1
index 7e8783b..c312d03 100644
--- a/tools/scripts/compile_release_package.ps1
+++ b/tools/scripts/compile_release_package.ps1
@@ -8,6 +8,17 @@ if ($args.Count -eq 0 -or ($args[0] -ne "x64" -and $args[0] -ne "x86"))
return
}
+$skipbuild = $false
+
+foreach ($arg in $args)
+{
+ if ($arg -eq "skipbuild")
+ {
+ Write-Host "skipbuild: Will skip the build process."
+ $skipbuild = $true
+ }
+}
+
# Check tool reachability
if ((Get-Command "compil32" -ErrorAction SilentlyContinue) -eq $null)
{
@@ -36,19 +47,53 @@ if ($target -eq "x86")
$platform = "Win32"
$copyFilesCmd = ".\copy_install_files.cmd"
$issFile = "..\innosetup\darkradiant.iss"
- $portableFilesFolder = "DarkRadiant_install"
+ $portablePath = "DarkRadiant_install"
}
else
{
$platform = "x64"
$copyFilesCmd = ".\copy_install_files.x64.cmd"
$issFile = "..\innosetup\darkradiant.x64.iss"
- $portableFilesFolder = "DarkRadiant_install.x64"
+ $portablePath = "DarkRadiant_install.x64"
}
-Start-Process "msbuild" -ArgumentList ("..\msvc2013\DarkRadiant.sln", "/p:configuration=release", "/t:rebuild", "/p:platform=$platform", "/maxcpucount:4") -NoNewWindow -Wait
+if (-not $skipbuild)
+{
+ Start-Process "msbuild" -ArgumentList ("..\msvc2015\DarkRadiant.sln", "/p:configuration=release", "/t:rebuild", "/p:platform=$platform", "/maxcpucount:4") -NoNewWindow -Wait
+}
+
+# Copy files to portable files folder
+
+$pathToCheck = "..\..\..\$portablePath"
+$portableFilesFolder = Get-Item -Path $pathToCheck
+
+if ($portableFilesFolder -eq $null)
+{
+ $portableFilesFolder = New-Item -Path $pathToCheck -ItemType Directory -ErrorAction Stop
+}
-Start-Process $copyFilesCmd -NoNewWindow -Wait
+Write-Host ("Clearing output folder {0}" -f $portableFilesFolder)
+Get-ChildItem -Path $portableFilesFolder | Remove-Item -Recurse -Force
+
+Write-Host ("Copying files...")
+
+$installFolder = Get-Item "..\..\install"
+$excludes = @('*.exp', '*.lib', '*.iobj', '*.ipdb', '*.suo', '*.pgd', '*.fbp', 'darkradiant.desktop.in')
+
+Get-ChildItem $installFolder -Recurse -Exclude $excludes | Copy-Item -Destination { Join-Path $portableFilesFolder $_.FullName.Substring($installFolder.FullName.Length) }
+
+# Copy the VC++ redist files
+$vcFolder = Get-Item "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.CRT" -Erroraction SilentlyContinue
+
+if ($vcFolder -ne $null)
+{
+ Get-ChildItem "msvcp140.dll" -Path $vcFolder | Copy-Item -Destination $portableFilesFolder
+ Get-ChildItem "vcruntime140.dll" -Path $vcFolder | Copy-Item -Destination $portableFilesFolder
+}
+else
+{
+ Write-Host -ForegroundColor Yellow "Warning: cannot find the VC++ redist folder, won't copy runtime DLLs."
+}
# Get the version from the innosetup file
$content = Get-Content $issFile
@@ -76,11 +121,11 @@ if ((Get-ChildItem -Path $portableFilename -ErrorAction SilentlyContinue) -ne $n
{
Remove-Item -Path $portableFilename
}
-Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList ("a", "-r", "-x!*.pdb", "-mx9", "-mmt2", $portableFilename, "..\..\..\$portableFilesFolder\*.*")
+Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList ("a", "-r", "-x!*.pdb", "-mx9", "-mmt2", $portableFilename, "..\..\..\$portablePath\*.*")
# Compress Program Database Files
if ((Get-ChildItem -Path $pdbFilename -ErrorAction SilentlyContinue) -ne $null)
{
Remove-Item -Path $pdbFilename
}
-Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList ("a", "-r", "-mx9", "-mmt2", $pdbFilename, "..\..\..\$portableFilesFolder\*.pdb") -Wait
+Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList ("a", "-r", "-mx9", "-mmt2", $pdbFilename, "..\..\..\$portablePath\*.pdb") -Wait
diff --git a/tools/scripts/copy_install_files.cmd b/tools/scripts/copy_install_files.cmd
deleted file mode 100644
index f758f2b..0000000
--- a/tools/scripts/copy_install_files.cmd
+++ /dev/null
@@ -1,10 +0,0 @@
-md ..\..\..\DarkRadiant_install
-del ..\..\..\DarkRadiant_install\*.* /S /Q
-xcopy ..\..\install\*.* /s ..\..\..\DarkRadiant_install\
-del ..\..\..\DarkRadiant_install\*.exp /S /Q
-rem del ..\..\..\DarkRadiant_install\*.pdb /S /Q
-del ..\..\..\DarkRadiant_install\*.lib /S /Q
-del ..\..\..\DarkRadiant_install\*.suo /S /Q
-del ..\..\..\DarkRadiant_install\*.pgd /S /Q
-del ..\..\..\DarkRadiant_install\*.fbp /S /Q
-del ..\..\..\DarkRadiant_install\darkradiant.desktop.in
\ No newline at end of file
diff --git a/tools/scripts/copy_install_files.x64.cmd b/tools/scripts/copy_install_files.x64.cmd
deleted file mode 100644
index 6d9434d..0000000
--- a/tools/scripts/copy_install_files.x64.cmd
+++ /dev/null
@@ -1,10 +0,0 @@
-md ..\..\..\DarkRadiant_install.x64
-del ..\..\..\DarkRadiant_install.x64\*.* /S /Q
-xcopy ..\..\install\*.* /s ..\..\..\DarkRadiant_install.x64\
-del ..\..\..\DarkRadiant_install.x64\*.exp /S /Q
-rem del ..\..\..\DarkRadiant_install.x64\*.pdb /S /Q
-del ..\..\..\DarkRadiant_install.x64\*.lib /S /Q
-del ..\..\..\DarkRadiant_install.x64\*.suo /S /Q
-del ..\..\..\DarkRadiant_install.x64\*.pgd /S /Q
-del ..\..\..\DarkRadiant_install.x64\*.fbp /S /Q
-del ..\..\..\DarkRadiant_install.x64\darkradiant.desktop.in
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/darkradiant.git
More information about the Pkg-games-commits
mailing list