// Project Lab - NHTV IGAD ////////////////////////////////////////// // Author: Yoshi van Belkom - 130118 ////////////////////////////////////////// #include "SkillTreeEditorPrivatePCH.h" #include "SkillTreeEditorViewportClient.h" #include "SceneViewport.h" #include "PreviewScene.h" #include "ScopedTransaction.h" #include "Runtime/Engine/Public/ComponentReregisterContext.h" #include "AssetToolsModule.h" #include "AssetRegistryModule.h" #include "CanvasTypes.h" #include "CanvasItem.h" #include "PhysicsEngine/BodySetup2D.h" #include "SEditorViewport.h" #include "SNotificationList.h" #include "NotificationManager.h" #include "SkillTreeFactory.h" #include "SkillTreeObject.h" #include "SkillObject.h" #define LOCTEXT_NAMESPACE "SkillTreeEditor" FSkillTreeEditorViewportClient::FSkillTreeEditorViewportClient( TWeakPtr a_skillTreeEditor, TWeakPtr a_skillTreeEditorViewportPtr ) : FEditorViewportClient( new FAssetEditorModeManager(), nullptr, a_skillTreeEditorViewportPtr ) , m_skillTreeEditorPtr( a_skillTreeEditor ) , m_skillTreeEditorViewportPtr( a_skillTreeEditorViewportPtr ) { check( m_skillTreeEditorPtr.IsValid() && m_skillTreeEditorViewportPtr.IsValid() ); // The tile map editor fully supports mode tools and isn't doing any incompatible stuff with the Widget Widget->SetUsesEditorModeTools( ModeTools ); PreviewScene = &m_ownedPreviewScene; ((FAssetEditorModeManager*)ModeTools)->SetPreviewScene( PreviewScene ); SetRealtime( true ); DrawHelper.bDrawGrid = false; EngineShowFlags.DisableAdvancedFeatures(); EngineShowFlags.CompositeEditorPrimitives = false; //REMINDER: Turned off. } void FSkillTreeEditorViewportClient::Draw( const FSceneView* a_view, FPrimitiveDrawInterface* a_drawInterface ) { FEditorViewportClient::Draw( a_view, a_drawInterface ); } void FSkillTreeEditorViewportClient::DrawCanvas( FViewport& a_viewport, FSceneView& a_view, FCanvas& a_canvas ) { const bool isHitTesting = a_canvas.IsHitTesting(); if ( !isHitTesting ) { a_canvas.SetHitProxy( nullptr ); } if ( !m_skillTreeEditorPtr.IsValid() ) { return; } m_screenSize = a_viewport.GetSizeXY(); USkillTreeObject* skillTree = m_skillTreeEditorPtr.Pin()->GetSkillTreeBeingEdited(); USkillObject* skill = m_skillTreeEditorPtr.Pin()->GetSkillBeingEdited(); int offsetY = -m_hexSize; int height; int maxY; int width; if ( m_state ) { height = skill->hexMap.height; if ( height % 2 != 0 ) offsetY = m_hexSize; width = skill->hexMap.width; maxY = height - 1; } else { height = 16; width = 13; maxY = 15; } FLinearColor enabledColor = FLinearColor( 0.43f, 0.43f, 0.43f ); FLinearColor disabledColor = FLinearColor( 0.10f, 0.10f, 0.10f ); for ( float x = 0; x < width; x++ ) { maxY = (maxY == (height - 1) ? height : (height - 1)); offsetY = (offsetY == -m_hexSize ? 0 : -m_hexSize); for ( int y = 0; y < maxY; y++ ) { bool test; if ( m_state ) { test = skill->hexMap.Get( x, y ); } else { test = skillTree->hexMap.Get( x, y ); } FLinearColor hexColor = enabledColor; if ( !test ) { hexColor = disabledColor; } float X = (x - (((float)width) / 2.0f)) * m_hexSize * 2; float Y = ((y - (maxY / 2)) * m_hexSize * 2) + offsetY; FCanvasNGonItem hexagonBorder( FVector2D( ( m_screenSize.X / 2 ) + X, ( m_screenSize.Y / 2 ) + Y ), FVector2D( m_hexSize, m_hexSize ), 6, hexColor ); hexagonBorder.Draw( &a_canvas ); if ( m_state ) { FCanvasTextItem TextItem( FVector2D( ( m_screenSize.X / 2 ) + X, ( m_screenSize.Y / 2 ) + Y ), FText::Format( LOCTEXT( "PositionStr", "{0},{1}" ), FText::AsNumber( x ), FText::AsNumber( y ) ), GEngine->GetSmallFont(), FLinearColor::White ); TextItem.EnableShadow( FLinearColor::Black ); TextItem.bCentreX = true; TextItem.Draw( &a_canvas ); } } } float hexmapWidth = ( m_screenSize.X / 2 ) + ( ( ( width - 1 ) - ( ( (float)width ) / 2.0f ) ) * m_hexSize * 2 ); hexmapWidth += m_hexSize; int boxWidth = ( ( m_screenSize.X - hexmapWidth ) ); boxWidth = FMath::Clamp( boxWidth, 0, 150 ); if ( !m_state ) { for ( int i = 0, y = 50; i < skillTree->skills.Num(); i++, y += 20 ) { if ( !skillTree->skills[i] ) continue; if ( m_hoverY == i || m_skillTreeEditorPtr.Pin()->selectedY == i ) { int minboxX = m_screenSize.X - boxWidth; int minboxY = y; FCanvasBoxItem boxItem( FVector2D( minboxX, minboxY ), FVector2D( boxWidth, 20) ); if ( m_hoverY == i ) boxItem.SetColor( FLinearColor::Black ); if ( m_skillTreeEditorPtr.Pin()->selectedY == i ) boxItem.SetColor( FLinearColor::White ); boxItem.Draw( &a_canvas ); } FFormatNamedArguments args; args.Add( TEXT( "DirtyState" ), skillTree->skills[i]->GetOutermost()->IsDirty() ? FText::FromString( TEXT( "*" ) ) : FText::GetEmpty() ); args.Add( TEXT( "SkillName" ), FText::AsCultureInvariant( skillTree->skills[i]->GetName() ) ); const FText assetName = FText::Format( LOCTEXT( "SkillName", "{SkillName}{DirtyState}" ), args ); FCanvasTextItem TextItem( FVector2D( m_screenSize.X - ( ( m_screenSize.X - hexmapWidth ) / 2 ), y ), assetName, GEngine->GetSmallFont(), FLinearColor::White ); TextItem.EnableShadow( FLinearColor::Black ); TextItem.bCentreX = true; TextItem.Draw( &a_canvas ); } } int minboxX = 0; int minboxY = 50; FCanvasTileItem enabledColorSquare( FVector2D( 0, 50 ), FVector2D( boxWidth, 20 ), enabledColor ); FCanvasTileItem disabledColorSquare( FVector2D( 0, 70 ), FVector2D( boxWidth, 20 ), disabledColor ); enabledColorSquare.Draw( &a_canvas ); disabledColorSquare.Draw( &a_canvas ); FCanvasTextItem enabledTextItem( FVector2D( boxWidth / 2, 50 ), FText::FromString( TEXT( "Solid" ) ), GEngine->GetSmallFont(), FLinearColor::White ); enabledTextItem.EnableShadow( FLinearColor::Black ); enabledTextItem.bCentreX = true; enabledTextItem.Draw( &a_canvas ); FCanvasTextItem disabledTextItem( FVector2D( boxWidth / 2, 70 ), FText::FromString( TEXT( "Empty" ) ), GEngine->GetSmallFont(), FLinearColor::White ); disabledTextItem.EnableShadow( FLinearColor::Black ); disabledTextItem.bCentreX = true; disabledTextItem.Draw( &a_canvas ); FEditorViewportClient::DrawCanvas( a_viewport, a_view, a_canvas ); } void FSkillTreeEditorViewportClient::MouseMove( FViewport* a_viewport, int32 a_mouseX, int32 a_mouseY ) { if ( m_state ) return; USkillTreeObject* skillTree = m_skillTreeEditorPtr.Pin()->GetSkillTreeBeingEdited(); int width = 13; float hexmapWidth = ( m_screenSize.X / 2 ) + ( ( ( width - 1 ) - ( ( (float)width ) / 2.0f ) ) * m_hexSize * 2 ); hexmapWidth += m_hexSize; int minboxX = m_screenSize.X - ( ( m_screenSize.X - hexmapWidth ) ); int maxboxX = m_screenSize.X; for ( int i = 0, y = 50; i < skillTree->skills.Num(); i++, y += 20 ) { int minboxY = y; int maxboxY = y + 20; if ( !skillTree->skills[i] ) continue; if ( a_mouseX >= minboxX && a_mouseX <= maxboxX && a_mouseY >= minboxY && a_mouseY <= maxboxY ) { m_hoverY = i; FEditorViewportClient::MouseMove( a_viewport, a_mouseX, a_mouseY ); return; } } m_hoverY = -1; FEditorViewportClient::MouseMove( a_viewport, a_mouseX, a_mouseY ); } void FSkillTreeEditorViewportClient::InternalActivateNewMode( ) { //m_currentMode = a_newMode; Viewport->InvalidateHitProxy(); } FLinearColor FSkillTreeEditorViewportClient::GetBackgroundColor() const { return FLinearColor( 0.20f, 0.22f, 0.22f ); } void FSkillTreeEditorViewportClient::ActivateEditMode() { // Activate the skill tree edit mode ModeTools->SetToolkitHost( m_skillTreeEditorPtr.Pin()->GetToolkitHost() ); ModeTools->ActivateDefaultMode(); } void FSkillTreeEditorViewportClient::Tick( float a_deltaSeconds ) { FEditorViewportClient::Tick( a_deltaSeconds ); m_skillTreeEditorPtr.Pin()->UpdateSkills(); if ( !GIntraFrameDebuggingGameThread ) { m_ownedPreviewScene.GetWorld()->Tick( LEVELTICK_All, a_deltaSeconds ); } } void FSkillTreeEditorViewportClient::ProcessClick( FSceneView& a_view, HHitProxy* a_hitProxy, FKey a_key, EInputEvent a_event, uint32 a_hitX, uint32 a_hitY ) { bool handled = false; USkillTreeObject* skillTree = m_skillTreeEditorPtr.Pin()->GetSkillTreeBeingEdited(); USkillObject* skill = m_skillTreeEditorPtr.Pin()->GetSkillBeingEdited(); int offsetY = -m_hexSize; int height; int maxY; int width; if ( m_state ) { height = skill->hexMap.height; width = skill->hexMap.width; if ( height % 2 != 0 ) offsetY = m_hexSize; maxY = height-1; } else { height = 16; width = 13; maxY = 15; } FVector2D mpos( a_hitX, a_hitY ); for ( float x = 0; x < width; x++ ) { maxY = (maxY == (height - 1) ? height : (height - 1)); offsetY = ( offsetY == -m_hexSize ? 0 : -m_hexSize ); for ( int y = 0; y < maxY; y++ ) { float X = ( x - ( ( (float)width ) / 2.0f ) ) * m_hexSize * 2; float Y = ( ( y - ( maxY / 2 ) ) * m_hexSize * 2 ) + offsetY; FVector2D pos( ( m_screenSize.X / 2 ) + X, ( m_screenSize.Y / 2 ) + Y ); float dist = FVector2D::Distance( pos, mpos ); if ( dist <= m_hexSize ) { if ( !m_state ) { skillTree->hexMap.Invert( x, y ); skillTree->Modify(); skillTree->MarkPackageDirty(); skillTree->PostEditChange(); } else { skill->hexMap.Invert( x, y ); skill->Modify(); skill->MarkPackageDirty(); skill->PostEditChange(); } handled = true; Invalidate(); break; } } if ( handled ) { break; } } if ( !handled && !m_state ) { float hexmapWidth = ( m_screenSize.X / 2 ) + ( ( ( width - 1 ) - ( ( (float)width ) / 2.0f ) ) * m_hexSize * 2 ); hexmapWidth += m_hexSize; uint32 minboxX = m_screenSize.X - ( ( m_screenSize.X - hexmapWidth ) ); uint32 maxboxX = m_screenSize.X; for ( int i = 0, y = 50; i < skillTree->skills.Num(); i++, y += 20 ) { uint32 minboxY = y; uint32 maxboxY = y + 20; if ( !skillTree->skills[i] ) continue; if ( a_hitX >= minboxX && a_hitX <= maxboxX && a_hitY >= minboxY && a_hitY <= maxboxY ) { m_skillTreeEditorPtr.Pin()->selectedY = i; handled = true; USkillObject* tmpCast = skillTree->skills[i]->GetDefaultObject(); if ( tmpCast != NULL ) m_skillTreeEditorPtr.Pin()->SetSkillBeingEdited( tmpCast ); } } } if ( !handled ) { FEditorViewportClient::ProcessClick( a_view, a_hitProxy, a_key, a_event, a_hitX, a_hitY ); } } #undef LOCTEXT_NAMESPACE