First working version

This commit is contained in:
bernatx 2019-10-29 09:48:47 +01:00 committed by bernat
parent e93c938fbd
commit ed5588f4c3
10 changed files with 518 additions and 0 deletions

View File

@ -0,0 +1,23 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "CarlaExporter",
"Description": "Export geometry for using in Recast",
"Category": "Other",
"CreatedBy": "Carla Team",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": false,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "CarlaExporter",
"Type": "Editor",
"LoadingPhase": "Default"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,58 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class CarlaExporter : ModuleRules
{
public CarlaExporter(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"Projects",
"InputCore",
"UnrealEd",
"LevelEditor",
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"Physx",
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}

View File

@ -0,0 +1,254 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "CarlaExporter.h"
#include "CarlaExporterStyle.h"
#include "CarlaExporterCommands.h"
#include "Misc/MessageDialog.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "SlateBasics.h"
#include "SlateExtras.h"
#include "Runtime/Engine/Classes/Engine/Selection.h"
#include "Runtime/Engine/Classes/Engine/StaticMeshActor.h"
#include "Components/InstancedStaticMeshComponent.h"
#include "PhysicsEngine/BodySetup.h"
#include "PhysicsEngine/ConvexElem.h"
#include "PxTriangleMesh.h"
#include "PxVec3.h"
#include "LevelEditor.h"
#include <fstream>
#include <sstream>
static const FName CarlaExporterTabName("CarlaExporter");
#define LOCTEXT_NAMESPACE "FCarlaExporterModule"
void FCarlaExporterModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
FCarlaExporterStyle::Initialize();
FCarlaExporterStyle::ReloadTextures();
FCarlaExporterCommands::Register();
PluginCommands = MakeShareable(new FUICommandList);
PluginCommands->MapAction(
FCarlaExporterCommands::Get().PluginActionExportAsBlock,
FExecuteAction::CreateRaw(this, &FCarlaExporterModule::PluginButtonClickedBlock),
FCanExecuteAction());
PluginCommands->MapAction(
FCarlaExporterCommands::Get().PluginActionExportAsCross,
FExecuteAction::CreateRaw(this, &FCarlaExporterModule::PluginButtonClickedCross),
FCanExecuteAction());
PluginCommands->MapAction(
FCarlaExporterCommands::Get().PluginActionExportAsSide,
FExecuteAction::CreateRaw(this, &FCarlaExporterModule::PluginButtonClickedSide),
FCanExecuteAction());
PluginCommands->MapAction(
FCarlaExporterCommands::Get().PluginActionExportAsRoad,
FExecuteAction::CreateRaw(this, &FCarlaExporterModule::PluginButtonClickedRoad),
FCanExecuteAction());
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
{
TSharedPtr<FExtender> MenuExtender = MakeShareable(new FExtender());
MenuExtender->AddMenuExtension("WindowLayout", EExtensionHook::After, PluginCommands, FMenuExtensionDelegate::CreateRaw(this, &FCarlaExporterModule::AddMenuExtension));
LevelEditorModule.GetMenuExtensibilityManager()->AddExtender(MenuExtender);
}
{
TSharedPtr<FExtender> ToolbarExtender = MakeShareable(new FExtender);
ToolbarExtender->AddToolBarExtension("Settings", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FCarlaExporterModule::AddToolbarExtension));
LevelEditorModule.GetToolBarExtensibilityManager()->AddExtender(ToolbarExtender);
}
}
void FCarlaExporterModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
FCarlaExporterStyle::Shutdown();
FCarlaExporterCommands::Unregister();
}
void FCarlaExporterModule::PluginButtonClickedBlock()
{
PluginButtonClicked("block");
}
void FCarlaExporterModule::PluginButtonClickedRoad()
{
PluginButtonClicked("road");
}
void FCarlaExporterModule::PluginButtonClickedSide()
{
PluginButtonClicked("side");
}
void FCarlaExporterModule::PluginButtonClickedCross()
{
PluginButtonClicked("cross");
}
void FCarlaExporterModule::PluginButtonClicked(std::string type)
{
TArray<UObject*> BP_Actors;
TArray<AStaticMeshActor*> ActorsToSelect;
USelection* CurrentSelection = GEditor->GetSelectedActors();
int32 SelectionNum = CurrentSelection->GetSelectedObjects(AActor::StaticClass(), BP_Actors);
UWorld* World = GEditor->GetEditorWorldContext().World();
if (!World)
return;
if (SelectionNum == 0)
return;
//GEditor->SelectNone(true,true);
// get target path
FString Path = FPaths::ConvertRelativePathToFull(FPaths::ProjectSavedDir());
// build final name
std::ostringstream name;
name << TCHAR_TO_UTF8(*Path) << "exported_" << type << ".obj";
// create the file
std::ofstream f(name.str());
int offset = 1;
for (UObject* SelectedObject : BP_Actors)
{
AActor* TempActor = Cast<AActor>(SelectedObject);
if (!TempActor) continue;
f << "o " << TCHAR_TO_ANSI(*(TempActor->GetName())) << "\n";
TArray<UActorComponent*> Components = TempActor->GetComponentsByClass(UStaticMeshComponent::StaticClass());
// UE_LOG(LogTemp, Warning, TEXT("Components: %d"), Components.Num());
for (auto *Component : Components)
{
// check if is an instanced static mesh
UInstancedStaticMeshComponent* comp2 = Cast<UInstancedStaticMeshComponent>(Component);
if (comp2)
{
UBodySetup *body = comp2->GetBodySetup();
if (!body) continue;
// UE_LOG(LogTemp, Warning, TEXT("Get %d component instances"), comp2->GetInstanceCount());
for (int i=0; i<comp2->GetInstanceCount(); ++i)
{
f << "g instance_" << i << "\n";
// get the component position and transform
FTransform InstanceTransform;
comp2->GetInstanceTransform(i, InstanceTransform, true);
FVector InstanceLocation = InstanceTransform.GetTranslation();
// through all convex elements
for (const auto &mesh : body->TriMeshes)
{
// get data
PxU32 nbVerts = mesh->getNbVertices();
const PxVec3* convexVerts = mesh->getVertices();
const PxU16* indexBuffer = (PxU16 *) mesh->getTriangles();
// write all vertex
for(PxU32 j=0;j<nbVerts;j++)
{
const PxVec3 &v = convexVerts[j];
FVector vec(v.x, v.y, v.z);
FVector vec3 = InstanceTransform.TransformVector(vec);
FVector world(vec3.X, vec3.Y, vec3.Z);
f << "v " << std::fixed << InstanceLocation.X + world.X << " " << InstanceLocation.Z + world.Z << " " << InstanceLocation.Y + world.Y << "\n";
}
// write all faces
f << "usemtl " << type << "\n";
for (unsigned int k=0; k<mesh->getNbTriangles()*3;k+=3)
{
// inverse order for left hand
f << "f " << offset + indexBuffer[k+2] << " " << offset + indexBuffer[k+1] << " " << offset + indexBuffer[k] << "\n";
}
offset += nbVerts;
}
}
}
else
{
// try as static mesh
UStaticMeshComponent* comp = Cast<UStaticMeshComponent>(Component);
if (!comp) continue;
UBodySetup *body = comp->GetBodySetup();
if (!body)
continue;
f << "g " << TCHAR_TO_ANSI(*(comp->GetName())) << "\n";
// get the component position and transform
FTransform CompTransform = comp->GetComponentTransform();
FVector CompLocation = CompTransform.GetTranslation();
// through all convex elements
for (const auto &mesh : body->TriMeshes)
{
// get data
PxU32 nbVerts = mesh->getNbVertices();
const PxVec3* convexVerts = mesh->getVertices();
const PxU16* indexBuffer = (PxU16 *) mesh->getTriangles();
// write all vertex
for(PxU32 j=0;j<nbVerts;j++)
{
const PxVec3 &v = convexVerts[j];
FVector vec(v.x, v.y, v.z);
FVector vec3 = CompTransform.TransformVector(vec);
FVector world(CompLocation.X + vec3.X, CompLocation.Y + vec3.Y, CompLocation.Z + vec3.Z);
// f << "v " << std::fixed << world.X * 0.01f << " " << world.Z * 0.01f << " " << world.Y * 0.01f << "\n";
f << "v " << std::fixed << world.X << " " << world.Z << " " << world.Y << "\n";
}
// write all faces
f << "usemtl " << type << "\n";
int k = 0;
for (PxU32 i=0; i<mesh->getNbTriangles(); ++i)
{
// f << "f " << offset + indexBuffer[k] << " " << offset + indexBuffer[k+1] << " " << offset + indexBuffer[k+2] << "\n";
// inverse order for left hand
f << "f " << offset + indexBuffer[k+2] << " " << offset + indexBuffer[k+1] << " " << offset + indexBuffer[k] << "\n";
k += 3;
}
offset += nbVerts;
}
}
}
}
f.close();
}
void FCarlaExporterModule::AddMenuExtension(FMenuBuilder& Builder)
{
//Builder.AddMenuEntry(FCarlaExporterCommands::Get().PluginAction);
Builder.AddMenuEntry(FCarlaExporterCommands::Get().PluginActionExportAsBlock);
Builder.AddMenuEntry(FCarlaExporterCommands::Get().PluginActionExportAsRoad);
Builder.AddMenuEntry(FCarlaExporterCommands::Get().PluginActionExportAsSide);
Builder.AddMenuEntry(FCarlaExporterCommands::Get().PluginActionExportAsCross);
}
void FCarlaExporterModule::AddToolbarExtension(FToolBarBuilder& Builder)
{
//Builder.AddToolBarButton(FCarlaExporterCommands::Get().PluginAction);
// Builder.AddToolBarButton(FCarlaExporterCommands::Get().PluginActionExportAsBlock);
// Builder.AddToolBarButton(FCarlaExporterCommands::Get().PluginActionExportAsRoad);
// Builder.AddToolBarButton(FCarlaExporterCommands::Get().PluginActionExportAsSide);
// Builder.AddToolBarButton(FCarlaExporterCommands::Get().PluginActionExportAsCross);
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FCarlaExporterModule, CarlaExporter)

View File

@ -0,0 +1,16 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "CarlaExporterCommands.h"
#define LOCTEXT_NAMESPACE "FCarlaExporterModule"
void FCarlaExporterCommands::RegisterCommands()
{
// UI_COMMAND(PluginAction, "CarlaExporter", "Execute CarlaExporter action", EUserInterfaceActionType::Button, FInputGesture());
UI_COMMAND(PluginActionExportAsBlock, "Export as Blocks", "Exporter for Blocks", EUserInterfaceActionType::Button, FInputGesture());
UI_COMMAND(PluginActionExportAsRoad, "Export as Roads", "Exporter for Roads", EUserInterfaceActionType::Button, FInputGesture());
UI_COMMAND(PluginActionExportAsSide, "Export as Sidewalks", "Exporter for Sidewalks", EUserInterfaceActionType::Button, FInputGesture());
UI_COMMAND(PluginActionExportAsCross, "Export as Cross zones", "Exporter for Cross zones", EUserInterfaceActionType::Button, FInputGesture());
}
#undef LOCTEXT_NAMESPACE

View File

@ -0,0 +1,75 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "CarlaExporterStyle.h"
#include "CarlaExporter.h"
#include "Framework/Application/SlateApplication.h"
#include "Styling/SlateStyleRegistry.h"
#include "Slate/SlateGameResources.h"
#include "Interfaces/IPluginManager.h"
TSharedPtr< FSlateStyleSet > FCarlaExporterStyle::StyleInstance = NULL;
void FCarlaExporterStyle::Initialize()
{
if (!StyleInstance.IsValid())
{
StyleInstance = Create();
FSlateStyleRegistry::RegisterSlateStyle(*StyleInstance);
}
}
void FCarlaExporterStyle::Shutdown()
{
FSlateStyleRegistry::UnRegisterSlateStyle(*StyleInstance);
ensure(StyleInstance.IsUnique());
StyleInstance.Reset();
}
FName FCarlaExporterStyle::GetStyleSetName()
{
static FName StyleSetName(TEXT("CarlaExporterStyle"));
return StyleSetName;
}
#define IMAGE_BRUSH( RelativePath, ... ) FSlateImageBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
#define BOX_BRUSH( RelativePath, ... ) FSlateBoxBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
#define BORDER_BRUSH( RelativePath, ... ) FSlateBorderBrush( Style->RootToContentDir( RelativePath, TEXT(".png") ), __VA_ARGS__ )
#define TTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".ttf") ), __VA_ARGS__ )
#define OTF_FONT( RelativePath, ... ) FSlateFontInfo( Style->RootToContentDir( RelativePath, TEXT(".otf") ), __VA_ARGS__ )
const FVector2D Icon16x16(16.0f, 16.0f);
const FVector2D Icon20x20(20.0f, 20.0f);
const FVector2D Icon40x40(40.0f, 40.0f);
TSharedRef< FSlateStyleSet > FCarlaExporterStyle::Create()
{
TSharedRef< FSlateStyleSet > Style = MakeShareable(new FSlateStyleSet("CarlaExporterStyle"));
Style->SetContentRoot(IPluginManager::Get().FindPlugin("CarlaExporter")->GetBaseDir() / TEXT("Resources"));
Style->Set("CarlaExporter.PluginAction", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
Style->Set("CarlaExporter.PluginActionExportAsBlock", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
Style->Set("CarlaExporter.PluginActionExportAsRoad", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
Style->Set("CarlaExporter.PluginActionExportAsSide", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
Style->Set("CarlaExporter.PluginActionExportAsCross", new IMAGE_BRUSH(TEXT("ButtonIcon_40x"), Icon40x40));
return Style;
}
#undef IMAGE_BRUSH
#undef BOX_BRUSH
#undef BORDER_BRUSH
#undef TTF_FONT
#undef OTF_FONT
void FCarlaExporterStyle::ReloadTextures()
{
if (FSlateApplication::IsInitialized())
{
FSlateApplication::Get().GetRenderer()->ReloadTextureResources();
}
}
const ISlateStyle& FCarlaExporterStyle::Get()
{
return *StyleInstance;
}

View File

@ -0,0 +1,34 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
#include <string>
class FToolBarBuilder;
class FMenuBuilder;
class FCarlaExporterModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
/** This function will be bound to Command. */
void PluginButtonClicked(std::string type);
void PluginButtonClickedBlock();
void PluginButtonClickedRoad();
void PluginButtonClickedSide();
void PluginButtonClickedCross();
private:
void AddToolbarExtension(FToolBarBuilder& Builder);
void AddMenuExtension(FMenuBuilder& Builder);
private:
TSharedPtr<class FUICommandList> PluginCommands;
};

View File

@ -0,0 +1,27 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Framework/Commands/Commands.h"
#include "CarlaExporterStyle.h"
class FCarlaExporterCommands : public TCommands<FCarlaExporterCommands>
{
public:
FCarlaExporterCommands()
: TCommands<FCarlaExporterCommands>(TEXT("CarlaExporter"), NSLOCTEXT("Contexts", "CarlaExporter", "CarlaExporter Plugin"), NAME_None, FCarlaExporterStyle::GetStyleSetName())
{
}
// TCommands<> interface
virtual void RegisterCommands() override;
public:
// TSharedPtr< FUICommandInfo > PluginAction;
TSharedPtr< FUICommandInfo > PluginActionExportAsBlock;
TSharedPtr< FUICommandInfo > PluginActionExportAsRoad;
TSharedPtr< FUICommandInfo > PluginActionExportAsSide;
TSharedPtr< FUICommandInfo > PluginActionExportAsCross;
};

View File

@ -0,0 +1,31 @@
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Styling/SlateStyle.h"
class FCarlaExporterStyle
{
public:
static void Initialize();
static void Shutdown();
/** reloads textures used by slate renderer */
static void ReloadTextures();
/** @return The Slate style set for the Shooter game */
static const ISlateStyle& Get();
static FName GetStyleSetName();
private:
static TSharedRef< class FSlateStyleSet > Create();
private:
static TSharedPtr< class FSlateStyleSet > StyleInstance;
};