/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "pch.h" #include "ModeCharacter.h" #include "../../EditorCommon/ManipScene.h" #include "../../EditorCommon/QPropertyTree/QPropertyTree.h" #include <QToolBar> #include <QAction> #include "Expected.h" #include "DisplayParameters.h" #include "CharacterDocument.h" #include "CharacterDefinition.h" #include "CharacterToolForm.h" #include "CharacterList.h" #include "SceneContent.h" #include "Serialization.h" #include "GizmoSink.h" #include "CharacterGizmoManager.h" #include "CharacterToolSystem.h" #include "TransformPanel.h" namespace CharacterTool { ModeCharacter::ModeCharacter() : m_scene(new Manip::CScene()) , m_ignoreSceneSelectionChange(false) , m_transformPanel() { EXPECTED(connect(m_scene.get(), SIGNAL(SignalUndo()), this, SLOT(OnSceneUndo()))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalRedo()), this, SLOT(OnSceneRedo()))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalElementsChanged(unsigned int)), this, SLOT(OnSceneElementsChanged(unsigned int)))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalElementContinousChange(unsigned int)), this, SLOT(OnSceneElementContinousChange(unsigned int)))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalSelectionChanged()), this, SLOT(OnSceneSelectionChanged()))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalPropertiesChanged()), this, SLOT(OnScenePropertiesChanged()))); EXPECTED(connect(m_scene.get(), SIGNAL(SignalManipulationModeChanged()), this, SLOT(OnSceneManipulationModeChanged()))); } void ModeCharacter::Serialize(Serialization::IArchive& ar) { m_scene->Serialize(ar); } void ModeCharacter::EnterMode(const SModeContext& context) { m_character = context.character; m_document = context.document; m_system = context.system; m_transformPanel = context.transformPanel; m_layerPropertyTrees = context.layerPropertyTrees; m_scene->SetSpaceProvider(m_system->characterSpaceProvider.get()); m_system->gizmoSink->SetScene(m_scene.get()); m_system->characterGizmoManager->ReadGizmos(); m_window = context.window; EXPECTED(connect(m_document, SIGNAL(SignalBindPoseModeChanged()), SLOT(OnBindPoseModeChanged()))); EXPECTED(connect(m_document, SIGNAL(SignalDisplayOptionsChanged(const DisplayOptions&)), SLOT(OnDisplayOptionsChanged()))); EXPECTED(connect(m_system->characterGizmoManager.get(), SIGNAL(SignalSubselectionChanged(int)), SLOT(OnSubselectionChanged(int)))); EXPECTED(connect(m_system->characterGizmoManager.get(), SIGNAL(SignalGizmoChanged()), SLOT(OnGizmoChanged()))); EXPECTED(connect(m_transformPanel, SIGNAL(SignalChanged()), SLOT(OnTransformPanelChanged()))); EXPECTED(connect(m_transformPanel, SIGNAL(SignalChangeFinished()), SLOT(OnTransformPanelChangeFinished()))); EXPECTED(connect(m_transformPanel, SIGNAL(SignalSpaceChanged()), SLOT(OnTransformPanelSpaceChanged()))); m_transformPanel->SetSpace(m_scene->TransformationSpace()); WriteTransformPanel(); QToolBar* toolBar = context.toolbar; toolBar->setFloatable(false); m_actionMoveTool.reset(new QAction(QIcon(QString("Editor/Icons/animation/tool_move.png")), "Move", 0)); m_actionMoveTool->setPriority(QAction::LowPriority); m_actionMoveTool->setCheckable(true); EXPECTED(connect(m_actionMoveTool.get(), SIGNAL(triggered()), this, SLOT(OnActionMoveTool()))); toolBar->addAction(m_actionMoveTool.get()); m_actionRotateTool.reset(new QAction(QIcon(QString("Editor/Icons/animation/tool_rotate.png")), "Rotate", 0)); m_actionRotateTool->setPriority(QAction::LowPriority); m_actionRotateTool->setCheckable(true); EXPECTED(connect(m_actionRotateTool.get(), SIGNAL(triggered()), this, SLOT(OnActionRotateTool()))); toolBar->addAction(m_actionRotateTool.get()); m_actionScaleTool.reset(new QAction(QIcon(QString("Editor/Icons/animation/tool_scale.png")), "Scale", 0)); EXPECTED(connect(m_actionScaleTool.get(), SIGNAL(triggered()), this, SLOT(OnActionScaleTool()))); m_actionScaleTool->setPriority(QAction::LowPriority); m_actionScaleTool->setCheckable(true); toolBar->addAction(m_actionScaleTool.get()); OnSceneManipulationModeChanged(); UpdateToolbar(); } void ModeCharacter::LeaveMode() { EXPECTED(disconnect(m_transformPanel, SIGNAL(SignalChanged()), this, SLOT(OnTransformPanelChanged()))); EXPECTED(disconnect(m_transformPanel, SIGNAL(SignalChangeFinished()), this, SLOT(OnTransformPanelChangeFinished()))); EXPECTED(disconnect(m_transformPanel, SIGNAL(SignalSpaceChanged()), this, SLOT(OnTransformPanelSpaceChanged()))); EXPECTED(disconnect(m_document, SIGNAL(SignalBindPoseModeChanged()), this, SLOT(OnBindPoseModeChanged()))); EXPECTED(disconnect(m_system->characterGizmoManager.get(), SIGNAL(SignalSubselectionChanged(int)), this, SLOT(OnSubselectionChanged(int)))); EXPECTED(disconnect(m_system->characterGizmoManager.get(), SIGNAL(SignalGizmoChanged()), this, SLOT(OnGizmoChanged()))); m_system->gizmoSink->SetScene(0); m_document = 0; m_scene->SetSpaceProvider(0); m_layerPropertyTrees.clear(); } void ModeCharacter::OnTransformPanelChanged() { if (m_scene->TransformationSpace() != Manip::SPACE_LOCAL) { m_scene->SetSelectionTransform(m_scene->TransformationSpace(), m_transformPanel->Transform()); } OnSceneElementContinousChange((1 << GIZMO_LAYER_COUNT) - 1); } void ModeCharacter::OnTransformPanelSpaceChanged() { m_scene->SetTransformationSpace(m_transformPanel->Space()); WriteTransformPanel(); } void ModeCharacter::OnTransformPanelChangeFinished() { m_scene->SetSelectionTransform(m_scene->TransformationSpace(), m_transformPanel->Transform()); OnSceneElementsChanged((1 << GIZMO_LAYER_COUNT) - 1); } void ModeCharacter::OnSubselectionChanged(int layer) { const vector<const void*>& items = m_system->characterGizmoManager->Subselection(GizmoLayer(layer)); CharacterDefinition* cdf = m_document->GetLoadedCharacterDefinition(); if (!cdf) { return; } Manip::SSelectionSet selection; const Manip::SElements& elements = m_scene->Elements(); for (size_t i = 0; i < elements.size(); ++i) { bool selected = std::find(items.begin(), items.end(), elements[i].originalHandle) != items.end(); if (selected) { selection.Add(elements[i].id); } } m_ignoreSceneSelectionChange = true; m_scene->SetSelection(selection); m_ignoreSceneSelectionChange = false; } void ModeCharacter::OnGizmoChanged() { WriteTransformPanel(); } void ModeCharacter::OnBindPoseModeChanged() { UpdateToolbar(); } void ModeCharacter::OnDisplayOptionsChanged() { int characterFlag = (1 << GIZMO_LAYER_CHARACTER); int animationFlag = (1 << GIZMO_LAYER_ANIMATION); int visibilityMask = 0xfffffffff & ~characterFlag & ~animationFlag; if (m_system->document->GetDisplayOptions()->attachmentAndPoseModifierGizmos) { visibilityMask |= characterFlag; } if (m_system->document->GetDisplayOptions()->animation.animationEventGizmos) { visibilityMask |= animationFlag; } m_scene->SetVisibleLayerMask(visibilityMask); } void ModeCharacter::OnSceneSelectionChanged() { if (m_ignoreSceneSelectionChange) { return; } if (ExplorerEntry* entry = m_system->gizmoSink->ActiveEntry()) { if (!m_system->document->IsExplorerEntrySelected(entry)) { ExplorerEntries entries; entries.push_back(entry); m_document->SetSelectedExplorerEntries(entries, CharacterDocument::SELECT_DO_NOT_REWIND); } } vector<const void*> selection; GetPropertySelection(&selection); for (int layer = 0; layer < GIZMO_LAYER_COUNT; ++layer) { m_system->characterGizmoManager->SetSubselection((GizmoLayer)layer, selection); } WriteTransformPanel(); } void ModeCharacter::WriteTransformPanel() { if (!m_transformPanel) { return; } m_transformPanel->SetMode(m_scene->TransformationMode()); m_transformPanel->SetTransform(m_scene->GetSelectionTransform(m_scene->TransformationSpace())); bool enabled = false; if (m_scene->TransformationMode() == Manip::MODE_TRANSLATE && m_scene->SelectionCanBeMoved()) { enabled = true; } if (m_scene->TransformationMode() == Manip::MODE_ROTATE && m_scene->SelectionCanBeRotated()) { enabled = true; } m_transformPanel->SetEnabled(enabled); } void ModeCharacter::OnSceneManipulationModeChanged() { m_actionMoveTool->setChecked(m_scene->TransformationMode() == Manip::MODE_TRANSLATE); m_actionRotateTool->setChecked(m_scene->TransformationMode() == Manip::MODE_ROTATE); m_actionScaleTool->setChecked(m_scene->TransformationMode() == Manip::MODE_SCALE); WriteTransformPanel(); } static ExplorerEntry* EntryForGizmoLayer(GizmoLayer layer, System* system) { switch (layer) { case GIZMO_LAYER_CHARACTER: return system->document->GetActiveCharacterEntry(); case GIZMO_LAYER_ANIMATION: return system->document->GetActiveAnimationEntry(); default: return 0; } } void ModeCharacter::HandleSceneChange(int layerBits, bool continuous) { unsigned int bitsLeft = layerBits; for (int layer = 0; bitsLeft != 0; bitsLeft = bitsLeft >> 1, ++layer) { if (layer >= m_layerPropertyTrees.size()) { break; } QPropertyTree* tree = m_layerPropertyTrees[layer]; if (bitsLeft & 1) { if (tree) { tree->apply(continuous); if (continuous) { tree->revert(); } } if (layer == GIZMO_LAYER_SCENE) { m_system->scene->SignalChanged(continuous); } else if (ExplorerEntry* entry = EntryForGizmoLayer((GizmoLayer)layer, m_system)) { m_system->explorer->CheckIfModified(entry, "Transform", continuous); } } } if (continuous && layerBits & (1 << GIZMO_LAYER_CHARACTER)) { if (ExplorerEntry* entry = m_system->document->GetActiveCharacterEntry()) { EntryModifiedEvent ev; ev.subtree = SUBTREE_CHARACTERS; ev.id = entry->id; ev.continuousChange = true; m_document->OnCharacterModified(ev); } } WriteTransformPanel(); } void ModeCharacter::OnSceneElementsChanged(unsigned int layerBits) { HandleSceneChange(layerBits, false); } void ModeCharacter::OnSceneElementContinousChange(unsigned int layerBits) { HandleSceneChange(layerBits, true); ; } void ModeCharacter::OnSceneUndo() { ExplorerEntries entries; m_document->GetEntriesActiveInDocument(&entries); if (entries.empty()) { return; } m_system->explorer->UndoInOrder(entries); WriteTransformPanel(); } void ModeCharacter::OnSceneRedo() { ExplorerEntries entries; m_document->GetEntriesActiveInDocument(&entries); if (entries.empty()) { return; } m_system->explorer->RedoInOrder(entries); WriteTransformPanel(); } void ModeCharacter::OnScenePropertiesChanged() { } void ModeCharacter::GetPropertySelection(vector<const void*>* selection) const { selection->clear(); if (CharacterDefinition* cdf = m_document->GetLoadedCharacterDefinition()) { Manip::SElements selectedElements; m_scene->GetSelectedElements(&selectedElements); for (size_t i = 0; i < selectedElements.size(); ++i) { selection->push_back(selectedElements[i].originalHandle); } } } void ModeCharacter::SetPropertySelection(const vector<const void*>& items) { } void ModeCharacter::OnViewportRender(const SRenderContext& rc) { m_scene->OnViewportRender(rc); } void ModeCharacter::OnViewportKey(const SKeyEvent& ev) { m_scene->OnViewportKey(ev); } bool ModeCharacter::ProcessesViewportKey(const QKeySequence& key) { // we pass key press events to m_scene, so check if it wants to process the key // so that we don't get overridden by any active shortcuts return m_scene->ProcessesViewportKey(key); } void ModeCharacter::OnViewportMouse(const SMouseEvent& ev) { m_scene->OnViewportMouse(ev); } void ModeCharacter::OnActionRotateTool() { m_scene->SetTransformationMode(Manip::MODE_ROTATE); OnSceneManipulationModeChanged(); } void ModeCharacter::OnActionMoveTool() { m_scene->SetTransformationMode(Manip::MODE_TRANSLATE); OnSceneManipulationModeChanged(); } void ModeCharacter::OnActionScaleTool() { m_scene->SetTransformationMode(Manip::MODE_SCALE); OnSceneManipulationModeChanged(); } void ModeCharacter::UpdateToolbar() { if (!m_document) { return; } m_actionMoveTool->setEnabled(true); m_actionRotateTool->setEnabled(true); m_actionScaleTool->setEnabled(true); } } #include <CharacterTool/ModeCharacter.moc>