2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
# include "GameProjectGenerationPrivatePCH.h"
# include "SourceCodeNavigation.h"
# include "ClassViewerModule.h"
# include "ClassViewerFilter.h"
# include "Editor/ClassViewer/Private/SClassViewer.h"
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
# include "DesktopPlatformModule.h"
2014-07-14 21:16:56 -04:00
# include "Editor/Documentation/Public/IDocumentation.h"
2014-07-21 17:31:27 -04:00
# include "EditorClassUtils.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "GameProjectGeneration"
struct FParentClassItem
{
2014-05-16 07:26:51 -04:00
GameProjectUtils : : FNewClassInfo ParentClassInfo ;
2014-03-14 14:13:41 -04:00
2014-05-16 07:26:51 -04:00
FParentClassItem ( const GameProjectUtils : : FNewClassInfo & InParentClassInfo )
: ParentClassInfo ( InParentClassInfo )
2014-03-14 14:13:41 -04:00
{ }
} ;
class FNativeClassParentFilter : public IClassViewerFilter
{
public :
2014-08-04 18:21:05 -04:00
FNativeClassParentFilter ( const TSharedPtr < GameProjectUtils : : FModuleContextInfo > * InSelectedModuleInfoPtr )
: SelectedModuleInfoPtr ( InSelectedModuleInfoPtr )
{
}
2014-06-13 06:14:46 -04:00
virtual bool IsClassAllowed ( const FClassViewerInitializationOptions & InInitOptions , const UClass * InClass , TSharedRef < FClassViewerFilterFuncs > InFilterFuncs ) override
2014-03-14 14:13:41 -04:00
{
// You may not make native classes based on blueprint generated classes
const bool bIsBlueprintClass = ( InClass - > ClassGeneratedBy ! = NULL ) ;
// UObject is special cased to be extensible since it would otherwise not be since it doesn't pass the API check (intrinsic class).
const bool bIsExplicitlyUObject = ( InClass = = UObject : : StaticClass ( ) ) ;
2014-05-29 17:38:55 -04:00
// Is this class in the same module as our current module?
2014-03-14 14:13:41 -04:00
const FString ClassModuleName = InClass - > GetOutermost ( ) - > GetName ( ) . RightChop ( FString ( TEXT ( " /Script/ " ) ) . Len ( ) ) ;
2014-08-04 18:21:05 -04:00
const TSharedPtr < GameProjectUtils : : FModuleContextInfo > & ModuleInfo = * SelectedModuleInfoPtr ;
const bool bIsInDestinationModule = ( ModuleInfo . IsValid ( ) & & ModuleInfo - > ModuleName = = ClassModuleName ) ;
2014-03-14 14:13:41 -04:00
// You need API if you are either not UObject itself and you are not in the destination module
const bool bNeedsAPI = ! bIsExplicitlyUObject & & ! bIsInDestinationModule ;
// You may not make a class that is not DLL exported.
2014-05-29 17:38:42 -04:00
// MinimalAPI classes aren't compatible with the DLL export macro, but can still be used as a valid base
const bool bHasAPI = InClass - > HasAnyClassFlags ( CLASS_RequiredAPI ) | | InClass - > HasAnyClassFlags ( CLASS_MinimalAPI ) ;
2014-03-14 14:13:41 -04:00
// @todo should we support interfaces?
const bool bIsInterface = InClass - > IsChildOf ( UInterface : : StaticClass ( ) ) ;
return ! bIsBlueprintClass & & ( ! bNeedsAPI | | bHasAPI ) & & ! bIsInterface ;
}
2014-06-13 06:14:46 -04:00
virtual bool IsUnloadedClassAllowed ( const FClassViewerInitializationOptions & InInitOptions , const TSharedRef < const IUnloadedBlueprintData > InUnloadedClassData , TSharedRef < FClassViewerFilterFuncs > InFilterFuncs ) override
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-08-04 18:21:05 -04:00
private :
/** Pointer to the currently selected module in the new class dialog */
const TSharedPtr < GameProjectUtils : : FModuleContextInfo > * SelectedModuleInfoPtr ;
2014-03-14 14:13:41 -04:00
} ;
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SNewClassDialog : : Construct ( const FArguments & InArgs )
{
2014-08-04 18:21:05 -04:00
{
TArray < GameProjectUtils : : FModuleContextInfo > CurrentModules = GameProjectUtils : : GetCurrentProjectModules ( ) ;
check ( CurrentModules . Num ( ) ) ; // this should never happen since GetCurrentProjectModules is supposed to add a dummy runtime module if the project currently has no modules
2014-05-16 10:47:37 -04:00
2014-08-04 18:21:05 -04:00
AvailableModules . Reserve ( CurrentModules . Num ( ) ) ;
for ( const GameProjectUtils : : FModuleContextInfo & ModuleInfo : CurrentModules )
{
AvailableModules . Emplace ( MakeShareable ( new GameProjectUtils : : FModuleContextInfo ( ModuleInfo ) ) ) ;
}
}
// If we have a runtime module with the same name as our project, then use that
// Otherwise, set out default target module as the first runtime module in the list
{
const FString ProjectName = FApp : : GetGameName ( ) ;
for ( const auto & AvailableModule : AvailableModules )
{
if ( AvailableModule - > ModuleName = = ProjectName )
{
SelectedModuleInfo = AvailableModule ;
break ;
}
if ( AvailableModule - > ModuleType = = EHostType : : Runtime )
{
SelectedModuleInfo = AvailableModule ;
// keep going in case we find a better match
}
}
if ( ! SelectedModuleInfo . IsValid ( ) )
{
// No runtime modules? Just take the first available module then
SelectedModuleInfo = AvailableModules [ 0 ] ;
}
}
NewClassPath = SelectedModuleInfo - > ModuleSourcePath ;
2014-05-14 06:47:25 -04:00
ClassLocation = GameProjectUtils : : EClassLocation : : UserDefined ; // the first call to UpdateInputValidity will set this correctly based on NewClassPath
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
2014-05-16 07:26:51 -04:00
ParentClassInfo = GameProjectUtils : : FNewClassInfo ( InArgs . _Class ) ;
2014-03-14 14:13:41 -04:00
bShowFullClassTree = false ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
LastPeriodicValidityCheckTime = 0 ;
PeriodicValidityCheckFrequency = 4 ;
bLastInputValidityCheckSuccessful = true ;
2014-03-14 14:13:41 -04:00
bPreventPeriodicValidityChecksUntilNextChange = false ;
SetupParentClassItems ( ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
UpdateInputValidity ( ) ;
2014-03-14 14:13:41 -04:00
FClassViewerInitializationOptions Options ;
Options . Mode = EClassViewerMode : : ClassPicker ;
Options . DisplayMode = EClassViewerDisplayMode : : TreeView ;
Options . bIsActorsOnly = false ;
Options . bIsPlaceableOnly = false ;
Options . bIsBlueprintBaseOnly = false ;
Options . bShowUnloadedBlueprints = false ;
Options . bShowNoneOption = false ;
Options . bShowObjectRootClass = true ;
// Prevent creating native classes based on blueprint classes
2014-08-04 18:21:05 -04:00
Options . ClassFilter = MakeShareable ( new FNativeClassParentFilter ( & SelectedModuleInfo ) ) ;
2014-03-14 14:13:41 -04:00
ClassViewer = StaticCastSharedRef < SClassViewer > ( FModuleManager : : LoadModuleChecked < FClassViewerModule > ( " ClassViewer " ) . CreateClassViewer ( Options , FOnClassPicked : : CreateSP ( this , & SNewClassDialog : : OnAdvancedClassSelected ) ) ) ;
2014-07-21 17:31:27 -04:00
TSharedRef < SWidget > DocWidget = IDocumentation : : Get ( ) - > CreateAnchor ( TAttribute < FString > ( this , & SNewClassDialog : : GetSelectedParentDocLink ) ) ;
DocWidget - > SetVisibility ( TAttribute < EVisibility > ( this , & SNewClassDialog : : GetDocLinkVisibility ) ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
const float EditableTextHeight = 26.0f ;
2014-03-14 14:13:41 -04:00
ChildSlot
[
SNew ( SBorder )
2014-05-14 07:07:29 -04:00
. Padding ( FMargin ( 26 , 8 ) )
2014-03-14 14:13:41 -04:00
. BorderImage ( FEditorStyle : : GetBrush ( " Docking.Tab.ContentAreaBrush " ) )
[
2014-05-14 07:07:29 -04:00
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
2014-03-14 14:13:41 -04:00
[
2014-05-14 07:07:29 -04:00
SAssignNew ( MainWizard , SWizard )
. ShowPageList ( false )
. CanFinish ( this , & SNewClassDialog : : CanFinish )
. FinishButtonText ( LOCTEXT ( " FinishButtonText " , " Create Class " ) . ToString ( ) )
. FinishButtonToolTip ( LOCTEXT ( " FinishButtonToolTip " , " Creates the code files to add your new class. " ) . ToString ( ) )
. OnCanceled ( this , & SNewClassDialog : : CancelClicked )
. OnFinished ( this , & SNewClassDialog : : FinishClicked )
2014-05-16 07:26:51 -04:00
. InitialPageIndex ( ParentClassInfo . IsSet ( ) ? 1 : 0 )
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
// Choose parent class
+ SWizard : : Page ( )
[
SNew ( SVerticalBox )
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
// Title
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 20 , 0 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.PageTitle " )
. Text ( LOCTEXT ( " ParentClassTitle " , " Choose Parent Class " ) )
]
// Title spacer
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 2 , 0 , 8 )
[
SNew ( SSeparator )
]
// Page description and view options
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 10 )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.f )
. VAlign ( VAlign_Center )
2014-03-14 14:13:41 -04:00
[
SNew ( STextBlock )
2014-05-14 07:07:29 -04:00
. Text ( FText : : Format ( LOCTEXT ( " ChooseParentClassDescription " , " You are about to add a C++ source code file. To compile these files you must have {0} installed. " ) , FSourceCodeNavigation : : GetSuggestedSourceCodeIDE ( ) ) )
2014-03-14 14:13:41 -04:00
]
2014-05-14 07:07:29 -04:00
// Full tree checkbox
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 4 , 0 , 0 , 0 )
2014-03-14 14:13:41 -04:00
[
2014-05-14 07:07:29 -04:00
SNew ( SCheckBox )
. IsChecked ( this , & SNewClassDialog : : IsFullClassTreeChecked )
. OnCheckStateChanged ( this , & SNewClassDialog : : OnFullClassTreeChanged )
2014-03-14 14:13:41 -04:00
[
SNew ( STextBlock )
2014-05-14 07:07:29 -04:00
. Text ( LOCTEXT ( " FullClassTree " , " Show All Classes " ) )
2014-03-14 14:13:41 -04:00
]
]
]
2014-05-14 07:07:29 -04:00
// Add Code list
+ SVerticalBox : : Slot ( )
. FillHeight ( 1.f )
. Padding ( 0 , 10 )
2014-03-14 14:13:41 -04:00
[
2014-05-14 07:07:29 -04:00
SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " ToolPanel.GroupBorder " ) )
2014-03-14 14:13:41 -04:00
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
[
2014-05-14 07:07:29 -04:00
// Basic view
SAssignNew ( ParentClassListView , SListView < TSharedPtr < FParentClassItem > > )
. ListItemsSource ( & ParentClassItemsSource )
. SelectionMode ( ESelectionMode : : Single )
. ClearSelectionOnClick ( false )
. OnGenerateRow ( this , & SNewClassDialog : : MakeParentClassListViewWidget )
. OnMouseButtonDoubleClick ( this , & SNewClassDialog : : OnParentClassItemDoubleClicked )
. OnSelectionChanged ( this , & SNewClassDialog : : OnClassSelected )
. Visibility ( this , & SNewClassDialog : : GetBasicParentClassVisibility )
2014-03-14 14:13:41 -04:00
]
+ SVerticalBox : : Slot ( )
[
2014-05-14 07:07:29 -04:00
// Advanced view
SNew ( SBox )
. Visibility ( this , & SNewClassDialog : : GetAdvancedParentClassVisibility )
2014-03-14 14:13:41 -04:00
[
2014-05-14 07:07:29 -04:00
ClassViewer . ToSharedRef ( )
2014-03-14 14:13:41 -04:00
]
]
2014-05-14 07:07:29 -04:00
]
]
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
// Class selection
+ SVerticalBox : : Slot ( )
. Padding ( 30 , 2 )
. AutoHeight ( )
[
SNew ( SHorizontalBox )
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
// Class label
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
2014-07-14 16:50:34 -04:00
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " ParentClassLabel " , " Selected Class " ) )
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " ParentClassSourceLabel " , " Selected Class Source " ) )
]
2014-05-14 07:07:29 -04:00
]
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
2014-05-14 07:07:29 -04:00
// Class selection preview
+ SHorizontalBox : : Slot ( )
[
2014-07-14 16:50:34 -04:00
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
2014-07-21 17:31:27 -04:00
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : GetSelectedParentClassName )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
DocWidget
]
2014-07-14 16:50:34 -04:00
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. VAlign ( VAlign_Bottom )
. HAlign ( HAlign_Left )
. Padding ( 0.0f , 0.0f , 0.0f , 0.0f )
[
SNew ( SHyperlink )
. Style ( FCoreStyle : : Get ( ) , " Hyperlink " )
. TextStyle ( FEditorStyle : : Get ( ) , " DetailsView.GoToCodeHyperlinkStyle " )
. OnNavigate ( this , & SNewClassDialog : : OnEditCodeClicked )
. Text ( this , & SNewClassDialog : : GetSelectedParentClassFilename )
. ToolTipText ( LOCTEXT ( " GoToCode_ToolTip " , " Click to open this source file in a text editor " ) )
. Visibility ( this , & SNewClassDialog : : GetSourceHyperlinkVisibility )
]
2014-03-14 14:13:41 -04:00
]
]
]
2014-05-14 07:07:29 -04:00
// Name class
+ SWizard : : Page ( )
. OnEnter ( this , & SNewClassDialog : : OnNamePageEntered )
[
SNew ( SVerticalBox )
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
// Title
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 20 , 0 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.PageTitle " )
. Text ( this , & SNewClassDialog : : GetNameClassTitle )
]
// Title spacer
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 2 , 0 , 8 )
[
SNew ( SSeparator )
]
+ SVerticalBox : : Slot ( )
. FillHeight ( 1.f )
. Padding ( 0 , 10 )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 0 , 0 , 5 )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " ClassNameDescription " , " Enter a name for your new class. Class names may only contain alphanumeric characters, and may not contain a space. " ) )
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 0 , 0 , 2 )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " ClassNameDetails " , " When you click the \" Create \" button below, a header (.h) file and a source (.cpp) file will be made using this name. " ) )
]
// Name Error label
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 5 )
[
// Constant height, whether the label is visible or not
SNew ( SBox ) . HeightOverride ( 20 )
[
SNew ( SBorder )
. Visibility ( this , & SNewClassDialog : : GetNameErrorLabelVisibility )
. BorderImage ( FEditorStyle : : GetBrush ( " NewClassDialog.ErrorLabelBorder " ) )
. Content ( )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : GetNameErrorLabelText )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.ErrorLabelFont " )
]
]
]
// Properties
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( SBorder )
. BorderImage ( FEditorStyle : : GetBrush ( " DetailsView.CategoryTop " ) )
. BorderBackgroundColor ( FLinearColor ( 0.6f , 0.6f , 0.6f , 1.0f ) )
. Padding ( FMargin ( 6.0f , 4.0f , 7.0f , 4.0f ) )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 )
[
SNew ( SGridPanel )
. FillColumn ( 1 , 1.0f )
// Name label
+ SGridPanel : : Slot ( 0 , 0 )
2014-03-14 14:13:41 -04:00
. VAlign ( VAlign_Center )
2014-05-14 07:07:29 -04:00
. Padding ( 0 , 0 , 12 , 0 )
2014-03-14 14:13:41 -04:00
[
SNew ( STextBlock )
2014-05-14 07:07:29 -04:00
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " NameLabel " , " Name " ) )
2014-03-14 14:13:41 -04:00
]
2014-05-14 07:07:29 -04:00
// Name edit box
+ SGridPanel : : Slot ( 1 , 0 )
. Padding ( 0.0f , 3.0f )
2014-03-14 14:13:41 -04:00
. VAlign ( VAlign_Center )
[
2014-05-14 07:07:29 -04:00
SNew ( SBox )
. HeightOverride ( EditableTextHeight )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
[
SAssignNew ( ClassNameEditBox , SEditableTextBox )
. Text ( this , & SNewClassDialog : : OnGetClassNameText )
. OnTextChanged ( this , & SNewClassDialog : : OnClassNameTextChanged )
]
2014-08-04 18:21:05 -04:00
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 6.0f , 0.0f , 0.0f , 0.0f )
[
SAssignNew ( AvailableModulesCombo , SComboBox < TSharedPtr < GameProjectUtils : : FModuleContextInfo > > )
. ToolTipText ( LOCTEXT ( " ModuleComboToolTip " , " Choose the target module for your new class " ) )
. OptionsSource ( & AvailableModules )
. InitiallySelectedItem ( SelectedModuleInfo )
. OnSelectionChanged ( this , & SNewClassDialog : : SelectedModuleComboBoxSelectionChanged )
. OnGenerateWidget ( this , & SNewClassDialog : : MakeWidgetForSelectedModuleCombo )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : GetSelectedModuleComboText )
]
]
2014-05-14 07:07:29 -04:00
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 6.0f , 0.0f , 0.0f , 0.0f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SCheckBox )
. Style ( FEditorStyle : : Get ( ) , " Property.ToggleButton.Start " )
. IsEnabled ( this , & SNewClassDialog : : CanChangeClassLocation )
. IsChecked ( this , & SNewClassDialog : : IsClassLocationActive , GameProjectUtils : : EClassLocation : : Public )
. OnCheckStateChanged ( this , & SNewClassDialog : : OnClassLocationChanged , GameProjectUtils : : EClassLocation : : Public )
. ToolTipText ( this , & SNewClassDialog : : GetClassLocationTooltip , GameProjectUtils : : EClassLocation : : Public )
[
SNew ( SBox )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Left )
. Padding ( FMargin ( 4.0f , 0.0f , 3.0f , 0.0f ) )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " Public " , " Public " ) )
. ColorAndOpacity ( this , & SNewClassDialog : : GetClassLocationTextColor , GameProjectUtils : : EClassLocation : : Public )
]
]
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SCheckBox )
. Style ( FEditorStyle : : Get ( ) , " Property.ToggleButton.End " )
. IsEnabled ( this , & SNewClassDialog : : CanChangeClassLocation )
. IsChecked ( this , & SNewClassDialog : : IsClassLocationActive , GameProjectUtils : : EClassLocation : : Private )
. OnCheckStateChanged ( this , & SNewClassDialog : : OnClassLocationChanged , GameProjectUtils : : EClassLocation : : Private )
. ToolTipText ( this , & SNewClassDialog : : GetClassLocationTooltip , GameProjectUtils : : EClassLocation : : Private )
[
SNew ( SBox )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Right )
. Padding ( FMargin ( 3.0f , 0.0f , 4.0f , 0.0f ) )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " Private " , " Private " ) )
. ColorAndOpacity ( this , & SNewClassDialog : : GetClassLocationTextColor , GameProjectUtils : : EClassLocation : : Private )
]
]
]
]
]
2014-03-14 14:13:41 -04:00
]
2014-05-14 07:07:29 -04:00
// Path label
+ SGridPanel : : Slot ( 0 , 1 )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " PathLabel " , " Path " ) . ToString ( ) )
]
// Path edit box
+ SGridPanel : : Slot ( 1 , 1 )
. Padding ( 0.0f , 3.0f )
. VAlign ( VAlign_Center )
[
SNew ( SBox )
. HeightOverride ( EditableTextHeight )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
[
SNew ( SEditableTextBox )
. Text ( this , & SNewClassDialog : : OnGetClassPathText )
. OnTextChanged ( this , & SNewClassDialog : : OnClassPathTextChanged )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 6.0f , 1.0f , 0.0f , 0.0f )
[
SNew ( SButton )
. VAlign ( VAlign_Center )
. OnClicked ( this , & SNewClassDialog : : HandleChooseFolderButtonClicked )
. Text ( LOCTEXT ( " BrowseButtonText " , " Choose Folder " ) )
]
]
]
// Header output label
+ SGridPanel : : Slot ( 0 , 2 )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " HeaderFileLabel " , " Header File " ) . ToString ( ) )
]
// Header output text
+ SGridPanel : : Slot ( 1 , 2 )
. Padding ( 0.0f , 3.0f )
. VAlign ( VAlign_Center )
[
SNew ( SBox )
. VAlign ( VAlign_Center )
. HeightOverride ( EditableTextHeight )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : OnGetClassHeaderFileText )
]
]
// Source output label
+ SGridPanel : : Slot ( 0 , 3 )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 12 , 0 )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.SelectedParentClassLabel " )
. Text ( LOCTEXT ( " SourceFileLabel " , " Source File " ) . ToString ( ) )
]
// Source output text
+ SGridPanel : : Slot ( 1 , 3 )
. Padding ( 0.0f , 3.0f )
. VAlign ( VAlign_Center )
[
SNew ( SBox )
. VAlign ( VAlign_Center )
. HeightOverride ( EditableTextHeight )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : OnGetClassSourceFileText )
]
]
]
2014-03-14 14:13:41 -04:00
]
2014-05-14 07:07:29 -04:00
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0.0f )
[
SNew ( SBorder )
. Padding ( FMargin ( 0.0f , 3.0f , 0.0f , 0.0f ) )
. BorderImage ( FEditorStyle : : GetBrush ( " DetailsView.CategoryBottom " ) )
. BorderBackgroundColor ( FLinearColor ( 0.6f , 0.6f , 0.6f , 1.0f ) )
]
2014-03-14 14:13:41 -04:00
]
2014-05-14 07:07:29 -04:00
]
]
// IDE download information
+ SVerticalBox : : Slot ( )
. Padding ( 0 , 5 )
. AutoHeight ( )
[
SNew ( SBorder )
. Visibility ( this , & SNewClassDialog : : GetGlobalErrorLabelVisibility )
. BorderImage ( FEditorStyle : : GetBrush ( " NewClassDialog.ErrorLabelBorder " ) )
. Content ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( this , & SNewClassDialog : : GetGlobalErrorLabelText )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.ErrorLabelFont " )
]
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
SNew ( SHyperlink )
. Text ( FText : : Format ( LOCTEXT ( " IDEDownloadLinkText " , " Download {0} " ) , FSourceCodeNavigation : : GetSuggestedSourceCodeIDE ( ) ) )
. OnNavigate ( this , & SNewClassDialog : : OnDownloadIDEClicked , FSourceCodeNavigation : : GetSuggestedSourceCodeIDEDownloadURL ( ) )
. Visibility ( this , & SNewClassDialog : : GetGlobalErrorLabelIDELinkVisibility )
]
]
2014-03-14 14:13:41 -04:00
]
]
] ;
// Select the first item
if ( InArgs . _Class = = NULL & & ParentClassItemsSource . Num ( ) > 0 )
{
ParentClassListView - > SetSelection ( ParentClassItemsSource [ 0 ] , ESelectInfo : : Direct ) ;
}
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SNewClassDialog : : Tick ( const FGeometry & AllottedGeometry , const double InCurrentTime , const float InDeltaTime )
{
SCompoundWidget : : Tick ( AllottedGeometry , InCurrentTime , InDeltaTime ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
// Every few seconds, the class name/path is checked for validity in case the disk contents changed and the location is now valid or invalid.
2014-03-14 14:13:41 -04:00
// After class creation, periodic checks are disabled to prevent a brief message indicating that the class you created already exists.
// This feature is re-enabled if the user did not restart and began editing parameters again.
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
if ( ! bPreventPeriodicValidityChecksUntilNextChange & & ( InCurrentTime > LastPeriodicValidityCheckTime + PeriodicValidityCheckFrequency ) )
2014-03-14 14:13:41 -04:00
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
UpdateInputValidity ( ) ;
2014-03-14 14:13:41 -04:00
}
}
TSharedRef < ITableRow > SNewClassDialog : : MakeParentClassListViewWidget ( TSharedPtr < FParentClassItem > ParentClassItem , const TSharedRef < STableViewBase > & OwnerTable )
{
if ( ! ensure ( ParentClassItem . IsValid ( ) ) )
{
return SNew ( STableRow < TSharedPtr < FParentClassItem > > , OwnerTable ) ;
}
2014-05-16 07:26:51 -04:00
if ( ! ParentClassItem - > ParentClassInfo . IsSet ( ) )
2014-03-14 14:13:41 -04:00
{
return SNew ( STableRow < TSharedPtr < FParentClassItem > > , OwnerTable ) ;
}
2014-05-16 07:26:51 -04:00
const FString ClassName = ParentClassItem - > ParentClassInfo . GetClassName ( ) ;
const FString ClassDescription = ParentClassItem - > ParentClassInfo . GetClassDescription ( ) ;
const FSlateBrush * const ClassBrush = ParentClassItem - > ParentClassInfo . GetClassIcon ( ) ;
2014-07-30 13:01:03 -04:00
const UClass * Class = ParentClassItem - > ParentClassInfo . BaseClass ;
2014-03-14 14:13:41 -04:00
2014-05-14 07:07:29 -04:00
const int32 ItemHeight = 64 ;
const int32 DescriptionIndent = 32 ;
2014-03-14 14:13:41 -04:00
return
SNew ( STableRow < TSharedPtr < FParentClassItem > > , OwnerTable )
. Style ( FEditorStyle : : Get ( ) , " NewClassDialog.ParentClassListView.TableRow " )
2014-07-30 13:01:03 -04:00
. ToolTip ( IDocumentation : : Get ( ) - > CreateToolTip ( FText : : FromString ( ClassDescription ) , nullptr , FEditorClassUtils : : GetDocumentationPage ( Class ) , FEditorClassUtils : : GetDocumentationExcerpt ( Class ) ) )
2014-03-14 14:13:41 -04:00
[
SNew ( SBox ) . HeightOverride ( ItemHeight )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. Padding ( 8 )
. AutoHeight ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 0 , 0 , 4 , 0 )
[
SNew ( SImage )
. ColorAndOpacity ( FSlateColor : : UseForeground ( ) )
. Image ( ClassBrush )
]
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. TextStyle ( FEditorStyle : : Get ( ) , " NewClassDialog.ParentClassItemTitle " )
. Text ( ClassName )
]
]
+ SVerticalBox : : Slot ( )
. FillHeight ( 1.f )
. Padding ( DescriptionIndent , 0 , 0 , 0 )
[
SNew ( STextBlock )
2014-05-14 07:07:29 -04:00
//.AutoWrapText(true)
2014-03-14 14:13:41 -04:00
. Text ( ClassDescription )
]
]
] ;
}
FString SNewClassDialog : : GetSelectedParentClassName ( ) const
{
2014-05-16 07:26:51 -04:00
return ParentClassInfo . IsSet ( ) ? ParentClassInfo . GetClassName ( ) : TEXT ( " " ) ;
2014-03-14 14:13:41 -04:00
}
2014-07-14 16:50:34 -04:00
FString GetClassHeaderPath ( const UClass * Class )
{
if ( Class )
{
FString ClassHeaderPath ;
if ( FSourceCodeNavigation : : FindClassHeaderPath ( Class , ClassHeaderPath ) & & IFileManager : : Get ( ) . FileSize ( * ClassHeaderPath ) ! = INDEX_NONE )
{
return ClassHeaderPath ;
}
}
return FString ( ) ;
}
EVisibility SNewClassDialog : : GetSourceHyperlinkVisibility ( ) const
{
return ( GetClassHeaderPath ( ParentClassInfo . BaseClass ) . Len ( ) > 0 ? EVisibility : : Visible : EVisibility : : Hidden ) ;
}
FString SNewClassDialog : : GetSelectedParentClassFilename ( ) const
{
const FString ClassHeaderPath = GetClassHeaderPath ( ParentClassInfo . BaseClass ) ;
if ( ClassHeaderPath . Len ( ) > 0 )
{
return FPaths : : GetCleanFilename ( * ClassHeaderPath ) ;
}
return FString ( ) ;
}
2014-07-21 17:31:27 -04:00
EVisibility SNewClassDialog : : GetDocLinkVisibility ( ) const
{
return ( ParentClassInfo . BaseClass = = nullptr | | FEditorClassUtils : : GetDocumentationLink ( ParentClassInfo . BaseClass ) . IsEmpty ( ) ? EVisibility : : Hidden : EVisibility : : Visible ) ;
}
FString SNewClassDialog : : GetSelectedParentDocLink ( ) const
{
return FEditorClassUtils : : GetDocumentationLink ( ParentClassInfo . BaseClass ) ;
}
2014-07-14 16:50:34 -04:00
void SNewClassDialog : : OnEditCodeClicked ( )
{
const FString ClassHeaderPath = GetClassHeaderPath ( ParentClassInfo . BaseClass ) ;
if ( ClassHeaderPath . Len ( ) > 0 )
{
const FString AbsoluteHeaderPath = IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * ClassHeaderPath ) ;
FSourceCodeNavigation : : OpenSourceFile ( AbsoluteHeaderPath ) ;
}
}
2014-03-14 14:13:41 -04:00
void SNewClassDialog : : OnParentClassItemDoubleClicked ( TSharedPtr < FParentClassItem > TemplateItem )
{
// Advance to the name page
const int32 NamePageIdx = 1 ;
if ( MainWizard - > CanShowPage ( NamePageIdx ) )
{
MainWizard - > ShowPage ( NamePageIdx ) ;
}
}
void SNewClassDialog : : OnClassSelected ( TSharedPtr < FParentClassItem > Item , ESelectInfo : : Type SelectInfo )
{
if ( Item . IsValid ( ) )
{
ClassViewer - > ClearSelection ( ) ;
2014-05-16 07:26:51 -04:00
ParentClassInfo = Item - > ParentClassInfo ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-05-16 07:26:51 -04:00
ParentClassInfo = GameProjectUtils : : FNewClassInfo ( ) ;
2014-03-14 14:13:41 -04:00
}
}
void SNewClassDialog : : OnAdvancedClassSelected ( UClass * Class )
{
ParentClassListView - > ClearSelection ( ) ;
2014-05-16 07:26:51 -04:00
ParentClassInfo = GameProjectUtils : : FNewClassInfo ( Class ) ;
2014-03-14 14:13:41 -04:00
}
ESlateCheckBoxState : : Type SNewClassDialog : : IsFullClassTreeChecked ( ) const
{
return bShowFullClassTree ? ESlateCheckBoxState : : Checked : ESlateCheckBoxState : : Unchecked ;
}
void SNewClassDialog : : OnFullClassTreeChanged ( ESlateCheckBoxState : : Type NewCheckedState )
{
bShowFullClassTree = ( NewCheckedState = = ESlateCheckBoxState : : Checked ) ;
}
EVisibility SNewClassDialog : : GetBasicParentClassVisibility ( ) const
{
return bShowFullClassTree ? EVisibility : : Collapsed : EVisibility : : Visible ;
}
EVisibility SNewClassDialog : : GetAdvancedParentClassVisibility ( ) const
{
return bShowFullClassTree ? EVisibility : : Visible : EVisibility : : Collapsed ;
}
EVisibility SNewClassDialog : : GetNameErrorLabelVisibility ( ) const
{
return GetNameErrorLabelText ( ) . IsEmpty ( ) ? EVisibility : : Hidden : EVisibility : : Visible ;
}
FString SNewClassDialog : : GetNameErrorLabelText ( ) const
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
if ( ! bLastInputValidityCheckSuccessful )
2014-03-14 14:13:41 -04:00
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
return LastInputValidityErrorText . ToString ( ) ;
2014-03-14 14:13:41 -04:00
}
return TEXT ( " " ) ;
}
EVisibility SNewClassDialog : : GetGlobalErrorLabelVisibility ( ) const
{
return GetGlobalErrorLabelText ( ) . IsEmpty ( ) ? EVisibility : : Hidden : EVisibility : : Visible ;
}
EVisibility SNewClassDialog : : GetGlobalErrorLabelIDELinkVisibility ( ) const
{
return FSourceCodeNavigation : : IsCompilerAvailable ( ) ? EVisibility : : Collapsed : EVisibility : : Visible ;
}
FString SNewClassDialog : : GetGlobalErrorLabelText ( ) const
{
if ( ! FSourceCodeNavigation : : IsCompilerAvailable ( ) )
{
return FText : : Format ( LOCTEXT ( " NoCompilerFound " , " No compiler was found. In order to use C++ code, you must first install {0}. " ) , FSourceCodeNavigation : : GetSuggestedSourceCodeIDE ( ) ) . ToString ( ) ;
}
return TEXT ( " " ) ;
}
void SNewClassDialog : : OnNamePageEntered ( )
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
// Set the default class name based on the selected parent class, eg MyActor
2014-05-16 07:26:51 -04:00
const FString ParentClassName = ParentClassInfo . GetClassNameCPP ( ) ;
const FString PotentialNewClassName = FString : : Printf ( TEXT ( " My%s " ) , ParentClassName . IsEmpty ( ) ? TEXT ( " Class " ) : * ParentClassName ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
// Only set the default if the user hasn't changed the class name from the previous default
if ( LastAutoGeneratedClassName . IsEmpty ( ) | | NewClassName = = LastAutoGeneratedClassName )
{
NewClassName = PotentialNewClassName ;
LastAutoGeneratedClassName = PotentialNewClassName ;
}
2014-05-16 07:26:51 -04:00
UpdateInputValidity ( ) ;
2014-03-14 14:13:41 -04:00
// Steal keyboard focus to accelerate name entering
FSlateApplication : : Get ( ) . SetKeyboardFocus ( ClassNameEditBox , EKeyboardFocusCause : : SetDirectly ) ;
}
FString SNewClassDialog : : GetNameClassTitle ( ) const
{
2014-05-16 07:26:51 -04:00
FString ParentClassName = GetSelectedParentClassName ( ) ;
if ( ParentClassName . IsEmpty ( ) | | ParentClassName = = " None " )
{
ParentClassName = TEXT ( " Class " ) ;
}
return FText : : Format ( LOCTEXT ( " NameClassTitle " , " Name Your New {0} " ) , FText : : FromString ( ParentClassName ) ) . ToString ( ) ;
2014-03-14 14:13:41 -04:00
}
FText SNewClassDialog : : OnGetClassNameText ( ) const
{
return FText : : FromString ( NewClassName ) ;
}
void SNewClassDialog : : OnClassNameTextChanged ( const FText & NewText )
{
NewClassName = NewText . ToString ( ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
UpdateInputValidity ( ) ;
}
FText SNewClassDialog : : OnGetClassPathText ( ) const
{
return FText : : FromString ( NewClassPath ) ;
}
void SNewClassDialog : : OnClassPathTextChanged ( const FText & NewText )
{
NewClassPath = NewText . ToString ( ) ;
2014-08-04 18:21:05 -04:00
// If the user has selected a path which matches the root of a known module, then update our selected module to be that module
for ( const auto & AvailableModule : AvailableModules )
{
if ( NewClassPath . StartsWith ( AvailableModule - > ModuleSourcePath ) )
{
SelectedModuleInfo = AvailableModule ;
AvailableModulesCombo - > SetSelectedItem ( SelectedModuleInfo ) ;
break ;
}
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
UpdateInputValidity ( ) ;
}
FText SNewClassDialog : : OnGetClassHeaderFileText ( ) const
{
return FText : : FromString ( CalculatedClassHeaderName ) ;
}
FText SNewClassDialog : : OnGetClassSourceFileText ( ) const
{
return FText : : FromString ( CalculatedClassSourceName ) ;
2014-03-14 14:13:41 -04:00
}
void SNewClassDialog : : CancelClicked ( )
{
CloseContainingWindow ( ) ;
}
bool SNewClassDialog : : CanFinish ( ) const
{
2014-05-16 07:26:51 -04:00
return bLastInputValidityCheckSuccessful & & ParentClassInfo . IsSet ( ) & & FSourceCodeNavigation : : IsCompilerAvailable ( ) ;
2014-03-14 14:13:41 -04:00
}
void SNewClassDialog : : FinishClicked ( )
{
check ( CanFinish ( ) ) ;
FString HeaderFilePath ;
FString CppFilePath ;
FText FailReason ;
2014-08-04 18:21:05 -04:00
if ( GameProjectUtils : : AddCodeToProject ( NewClassName , NewClassPath , * SelectedModuleInfo , ParentClassInfo , HeaderFilePath , CppFilePath , FailReason ) )
2014-03-14 14:13:41 -04:00
{
// Prevent periodic validity checks. This is to prevent a brief error message about the class already existing while you are exiting.
bPreventPeriodicValidityChecksUntilNextChange = true ;
if ( HeaderFilePath . IsEmpty ( ) | | CppFilePath . IsEmpty ( ) | | ! FSlateApplication : : Get ( ) . SupportsSourceAccess ( ) )
{
// Code successfully added, notify the user. We are either running on a platform that does not support source access or a file was not given so don't ask about editing the file
const FText Message = FText : : Format ( LOCTEXT ( " AddCodeSuccess " , " Successfully added class {0}. " ) , FText : : FromString ( NewClassName ) ) ;
FMessageDialog : : Open ( EAppMsgType : : Ok , Message ) ;
}
else
{
// Code successfully added, notify the user and ask about opening the IDE now
const FText Message = FText : : Format ( LOCTEXT ( " AddCodeSuccessWithSync " , " Successfully added class {0}. Would you like to edit the code now? " ) , FText : : FromString ( NewClassName ) ) ;
if ( FMessageDialog : : Open ( EAppMsgType : : YesNo , Message ) = = EAppReturnType : : Yes )
{
TArray < FString > SourceFiles ;
SourceFiles . Add ( IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * HeaderFilePath ) ) ;
SourceFiles . Add ( IFileManager : : Get ( ) . ConvertToAbsolutePathForExternalAppForRead ( * CppFilePath ) ) ;
FSourceCodeNavigation : : OpenSourceFiles ( SourceFiles ) ;
}
}
// Successfully created the code and potentially opened the IDE. Close the dialog.
CloseContainingWindow ( ) ;
}
else
{
// @todo show fail reason in error label
// Failed to add code
const FText Message = FText : : Format ( LOCTEXT ( " AddCodeFailed " , " Failed to add class {0}. {1} " ) , FText : : FromString ( NewClassName ) , FailReason ) ;
FMessageDialog : : Open ( EAppMsgType : : Ok , Message ) ;
}
}
void SNewClassDialog : : OnDownloadIDEClicked ( FString URL )
{
FPlatformProcess : : LaunchURL ( * URL , NULL , NULL ) ;
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
FReply SNewClassDialog : : HandleChooseFolderButtonClicked ( )
2014-03-14 14:13:41 -04:00
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
IDesktopPlatform * DesktopPlatform = FDesktopPlatformModule : : Get ( ) ;
if ( DesktopPlatform )
2014-03-14 14:13:41 -04:00
{
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
TSharedPtr < SWindow > ParentWindow = FSlateApplication : : Get ( ) . FindWidgetWindow ( AsShared ( ) ) ;
void * ParentWindowWindowHandle = ( ParentWindow . IsValid ( ) ) ? ParentWindow - > GetNativeWindow ( ) - > GetOSWindowHandle ( ) : nullptr ;
FString FolderName ;
const FString Title = LOCTEXT ( " NewClassBrowseTitle " , " Choose a source location " ) . ToString ( ) ;
const bool bFolderSelected = DesktopPlatform - > OpenDirectoryDialog (
ParentWindowWindowHandle ,
Title ,
NewClassPath ,
FolderName
) ;
if ( bFolderSelected )
{
if ( ! FolderName . EndsWith ( TEXT ( " / " ) ) )
{
FolderName + = TEXT ( " / " ) ;
}
NewClassPath = FolderName ;
2014-08-04 18:21:05 -04:00
// If the user has selected a path which matches the root of a known module, then update our selected module to be that module
for ( const auto & AvailableModule : AvailableModules )
{
if ( NewClassPath . StartsWith ( AvailableModule - > ModuleSourcePath ) )
{
SelectedModuleInfo = AvailableModule ;
AvailableModulesCombo - > SetSelectedItem ( SelectedModuleInfo ) ;
break ;
}
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
UpdateInputValidity ( ) ;
}
2014-03-14 14:13:41 -04:00
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
return FReply : : Handled ( ) ;
}
2014-08-04 18:21:05 -04:00
FText SNewClassDialog : : GetSelectedModuleComboText ( ) const
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " ModuleName " ) , FText : : FromString ( SelectedModuleInfo - > ModuleName ) ) ;
Args . Add ( TEXT ( " ModuleType " ) , FText : : FromString ( EHostType : : ToString ( SelectedModuleInfo - > ModuleType ) ) ) ;
return FText : : Format ( LOCTEXT ( " ModuleComboEntry " , " {ModuleName} ({ModuleType}) " ) , Args ) ;
}
void SNewClassDialog : : SelectedModuleComboBoxSelectionChanged ( TSharedPtr < GameProjectUtils : : FModuleContextInfo > Value , ESelectInfo : : Type SelectInfo )
{
const FString & OldModulePath = SelectedModuleInfo - > ModuleSourcePath ;
const FString & NewModulePath = Value - > ModuleSourcePath ;
SelectedModuleInfo = Value ;
// Update the class path to be rooted to the new module location
const FString AbsoluteClassPath = FPaths : : ConvertRelativePathToFull ( NewClassPath ) / " " ; // Ensure trailing /
if ( AbsoluteClassPath . StartsWith ( OldModulePath ) )
{
NewClassPath = AbsoluteClassPath . Replace ( * OldModulePath , * NewModulePath ) ;
}
UpdateInputValidity ( ) ;
}
TSharedRef < SWidget > SNewClassDialog : : MakeWidgetForSelectedModuleCombo ( TSharedPtr < GameProjectUtils : : FModuleContextInfo > Value )
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " ModuleName " ) , FText : : FromString ( Value - > ModuleName ) ) ;
Args . Add ( TEXT ( " ModuleType " ) , FText : : FromString ( EHostType : : ToString ( Value - > ModuleType ) ) ) ;
return SNew ( STextBlock )
. Text ( FText : : Format ( LOCTEXT ( " ModuleComboEntry " , " {ModuleName} ({ModuleType}) " ) , Args ) ) ;
}
2014-05-14 06:47:25 -04:00
FSlateColor SNewClassDialog : : GetClassLocationTextColor ( GameProjectUtils : : EClassLocation InLocation ) const
{
return ( ClassLocation = = InLocation ) ? FSlateColor ( FLinearColor ( 0 , 0 , 0 ) ) : FSlateColor ( FLinearColor ( 0.72f , 0.72f , 0.72f , 1.f ) ) ;
}
FText SNewClassDialog : : GetClassLocationTooltip ( GameProjectUtils : : EClassLocation InLocation ) const
{
if ( CanChangeClassLocation ( ) )
{
switch ( InLocation )
{
case GameProjectUtils : : EClassLocation : : Public :
return LOCTEXT ( " ClassLocation_Public " , " A public class can be included and used inside other modules in addition to the module it resides in " ) ;
case GameProjectUtils : : EClassLocation : : Private :
return LOCTEXT ( " ClassLocation_Private " , " A private class can only be included and used within the module it resides in " ) ;
default :
break ;
}
}
return LOCTEXT ( " ClassLocation_UserDefined " , " Your project is either not using a Public and Private source layout, or you're explicitly creating your class outside of the Public or Private folder " ) ;
}
ESlateCheckBoxState : : Type SNewClassDialog : : IsClassLocationActive ( GameProjectUtils : : EClassLocation InLocation ) const
{
return ( ClassLocation = = InLocation ) ? ESlateCheckBoxState : : Checked : ESlateCheckBoxState : : Unchecked ;
}
void SNewClassDialog : : OnClassLocationChanged ( ESlateCheckBoxState : : Type InCheckedState , GameProjectUtils : : EClassLocation InLocation )
{
if ( InCheckedState = = ESlateCheckBoxState : : Checked )
{
const FString AbsoluteClassPath = FPaths : : ConvertRelativePathToFull ( NewClassPath ) / " " ; // Ensure trailing /
GameProjectUtils : : EClassLocation TmpClassLocation = GameProjectUtils : : EClassLocation : : UserDefined ;
2014-08-04 18:21:05 -04:00
GameProjectUtils : : GetClassLocation ( AbsoluteClassPath , * SelectedModuleInfo , TmpClassLocation ) ;
2014-05-14 06:47:25 -04:00
2014-08-04 18:21:05 -04:00
const FString RootPath = SelectedModuleInfo - > ModuleSourcePath ;
2014-05-14 06:47:25 -04:00
const FString PublicPath = RootPath / " Public " / " " ; // Ensure trailing /
const FString PrivatePath = RootPath / " Private " / " " ; // Ensure trailing /
// Update the class path to be rooted to the Public or Private folder based on InVisibility
switch ( InLocation )
{
case GameProjectUtils : : EClassLocation : : Public :
if ( AbsoluteClassPath . StartsWith ( PrivatePath ) )
{
NewClassPath = AbsoluteClassPath . Replace ( * PrivatePath , * PublicPath ) ;
}
else if ( AbsoluteClassPath . StartsWith ( RootPath ) )
{
NewClassPath = AbsoluteClassPath . Replace ( * RootPath , * PublicPath ) ;
}
break ;
case GameProjectUtils : : EClassLocation : : Private :
if ( AbsoluteClassPath . StartsWith ( PublicPath ) )
{
NewClassPath = AbsoluteClassPath . Replace ( * PublicPath , * PrivatePath ) ;
}
else if ( AbsoluteClassPath . StartsWith ( RootPath ) )
{
NewClassPath = AbsoluteClassPath . Replace ( * RootPath , * PrivatePath ) ;
}
break ;
default :
break ;
}
// Will update ClassVisibility correctly
UpdateInputValidity ( ) ;
}
}
bool SNewClassDialog : : CanChangeClassLocation ( ) const
{
return ClassLocation ! = GameProjectUtils : : EClassLocation : : UserDefined ;
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
void SNewClassDialog : : UpdateInputValidity ( )
{
bLastInputValidityCheckSuccessful = true ;
// Validate the path first since this has the side effect of updating the UI
2014-08-04 18:21:05 -04:00
bLastInputValidityCheckSuccessful = GameProjectUtils : : CalculateSourcePaths ( NewClassPath , * SelectedModuleInfo , CalculatedClassHeaderName , CalculatedClassSourceName , & LastInputValidityErrorText ) ;
2014-05-16 07:26:51 -04:00
CalculatedClassHeaderName / = ParentClassInfo . GetHeaderFilename ( NewClassName ) ;
CalculatedClassSourceName / = ParentClassInfo . GetSourceFilename ( NewClassName ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
2014-05-14 06:47:25 -04:00
// If the source paths check as succeeded, check to see if we're using a Public/Private class
if ( bLastInputValidityCheckSuccessful )
{
2014-08-04 18:21:05 -04:00
GameProjectUtils : : GetClassLocation ( NewClassPath , * SelectedModuleInfo , ClassLocation ) ;
2014-05-14 06:47:25 -04:00
// We only care about the Public and Private folders
if ( ClassLocation ! = GameProjectUtils : : EClassLocation : : Public & & ClassLocation ! = GameProjectUtils : : EClassLocation : : Private )
{
ClassLocation = GameProjectUtils : : EClassLocation : : UserDefined ;
}
}
else
{
ClassLocation = GameProjectUtils : : EClassLocation : : UserDefined ;
}
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
// Validate the class name only if the path is valid
if ( bLastInputValidityCheckSuccessful )
{
2014-08-04 18:21:05 -04:00
bLastInputValidityCheckSuccessful = GameProjectUtils : : IsValidClassNameForCreation ( NewClassName , * SelectedModuleInfo , LastInputValidityErrorText ) ;
#ttp 322244 - LIVE: Feature Request: During "Add Code to Project", allow user to select path where files go
#proj UE4
#branch UE4
#summary You can now choose where to place a class added via the New Class Wizard
#extra This tries to be smart about your placement if you have Public and Private folders for your project.
- By default the header would go into Public, and the source file would go into Private.
- If you select the Public/Classes folder for the path, the source file will still go into Private.
- If you have a sub-path, eg) /Public/MyStuff/MyClass.h, this will be mirrored in the placement of the source file, eg) /Private/MyStuff/MyClass.cpp
#extra If you're not using Public or Private folders it will just place the source at whatever path you specified.
#extra It will verify that your source code is going to a valid module folder for your game, and also allows matching of modules that start with your game name, eg) MyGame, MyGameEditor.
#reviewedby Thomas.Sarkanen, Max.Preussner
[CL 2046528 by Jamie Dale in Main branch]
2014-04-23 18:50:08 -04:00
}
LastPeriodicValidityCheckTime = FSlateApplication : : Get ( ) . GetCurrentTime ( ) ;
2014-03-14 14:13:41 -04:00
// Since this function was invoked, periodic validity checks should be re-enabled if they were disabled.
bPreventPeriodicValidityChecksUntilNextChange = false ;
}
2014-05-16 07:26:51 -04:00
const GameProjectUtils : : FNewClassInfo & SNewClassDialog : : GetSelectedParentClassInfo ( ) const
2014-03-14 14:13:41 -04:00
{
2014-05-16 07:26:51 -04:00
return ParentClassInfo ;
2014-03-14 14:13:41 -04:00
}
void SNewClassDialog : : SetupParentClassItems ( )
{
2014-05-16 07:26:51 -04:00
TArray < GameProjectUtils : : FNewClassInfo > FeaturedClasses ;
2014-03-14 14:13:41 -04:00
2014-05-16 07:26:51 -04:00
// Add an empty class
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( GameProjectUtils : : FNewClassInfo : : EClassType : : EmptyCpp ) ) ;
2014-03-14 14:13:41 -04:00
// @todo make this ini configurable
2014-05-16 07:26:51 -04:00
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( ACharacter : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( APawn : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( AActor : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( APlayerCameraManager : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( APlayerController : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( AGameMode : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( AWorldSettings : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( AHUD : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( APlayerState : : StaticClass ( ) ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( AGameState : : StaticClass ( ) ) ) ;
// Add the extra non-UObject classes
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( GameProjectUtils : : FNewClassInfo : : EClassType : : SlateWidget ) ) ;
FeaturedClasses . Add ( GameProjectUtils : : FNewClassInfo ( GameProjectUtils : : FNewClassInfo : : EClassType : : SlateWidgetStyle ) ) ;
2014-03-14 14:13:41 -04:00
for ( auto ClassIt = FeaturedClasses . CreateConstIterator ( ) ; ClassIt ; + + ClassIt )
{
ParentClassItemsSource . Add ( MakeShareable ( new FParentClassItem ( * ClassIt ) ) ) ;
}
}
void SNewClassDialog : : CloseContainingWindow ( )
{
FWidgetPath WidgetPath ;
TSharedPtr < SWindow > ContainingWindow = FSlateApplication : : Get ( ) . FindWidgetWindow ( AsShared ( ) , WidgetPath ) ;
if ( ContainingWindow . IsValid ( ) )
{
ContainingWindow - > RequestDestroyWindow ( ) ;
}
}
# undef LOCTEXT_NAMESPACE