├── .gitattributes ├── .gitignore ├── Content └── Blueprints │ └── BP_ShpPolygonGenerator.uasset ├── LICENSE ├── README.md ├── Resources └── Icon128.png ├── ShpGeometry.uplugin └── Source ├── ShpGeometry ├── Private │ ├── ShpGeometryModule.cpp │ └── ShpPolygonActor.cpp ├── Public │ ├── ShpFileAsset.h │ ├── ShpGeometryModule.h │ ├── ShpPolygonActor.h │ └── ShpTypes │ │ └── ShpPolygon.h └── ShpGeometry.Build.cs └── ShpGeometryEditor ├── Private ├── AssetTools │ ├── ShpFileAssetActions.cpp │ └── ShpFileAssetActions.h ├── Factories │ ├── ShpFileAssetFactory.cpp │ └── ShpFileAssetFactory.h ├── ShpGeometryEditorModule.cpp └── Styles │ └── ShpFileAssetEditorStyle.h └── ShpGeometryEditor.Build.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | *.fbx filter=lfs diff=lfs merge=lfs -text 2 | *.blend filter=lfs diff=lfs merge=lfs -text 3 | *.obj filter=lfs diff=lfs merge=lfs -text 4 | *.png filter=lfs diff=lfs merge=lfs -text 5 | *.jpg filter=lfs diff=lfs merge=lfs -text 6 | *.jpeg filter=lfs diff=lfs merge=lfs -text 7 | *.hdr filter=lfs diff=lfs merge=lfs -text 8 | *.exr filter=lfs diff=lfs merge=lfs -text 9 | *.wav filter=lfs diff=lfs merge=lfs -text 10 | *.mp3 filter=lfs diff=lfs merge=lfs -text 11 | *.mp4 filter=lfs diff=lfs merge=lfs -text 12 | *.mov filter=lfs diff=lfs merge=lfs -text 13 | *.psd filter=lfs diff=lfs merge=lfs -text 14 | *.tga filter=lfs diff=lfs merge=lfs -text 15 | *.tif filter=lfs diff=lfs merge=lfs -text 16 | *.uasset filter=lfs diff=lfs merge=lfs -text 17 | *.umap filter=lfs diff=lfs merge=lfs -text 18 | *.upk filter=lfs diff=lfs merge=lfs -text 19 | *.udk filter=lfs diff=lfs merge=lfs -text 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Binaries/* 2 | Intermediate/* 3 | dist/* 4 | *.gch 5 | -------------------------------------------------------------------------------- /Content/Blueprints/BP_ShpPolygonGenerator.uasset: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ec290bad164224b37743ccb5ef65287ce2c09fea6874d601b004fe05e1680efd 3 | size 141132 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Petersen, Iwer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShpGeometry - Unreal Engine Plugin 2 | 3 | This plugins is intended to import geometry from ESRI shape files. This is a very early version that imports only polygon shapes into a ShpFileAsset, that can be used to generate ProceduralMeshComponents. 4 | 5 | ## Compatibility 6 | 7 | * Unreal Engine 4 is supported at least with 4.27 (branch ue4, tag ue4.27) 8 | * Unreal Engine 5 is supported up to 5.1 (on master branch) 9 | 10 | 11 | ## Building 12 | 13 | This plugin uses [GeoReference](https://github.com/iwer/GeoReference), [SpatialGeometryTools](https://github.com/iwer/SpatialGeometryTools), [UnrealGDAL](https://github.com/TensorWorks/UnrealGDAL), [ue4cli](https://github.com/adamrehn/ue4cli) and [conan-ue4cli](https://github.com/adamrehn/conan-ue4cli) to build and manage the required GDAL libraries. 14 | 15 | * Download a Release of UnrealGDAL and place it in the Plugins directory or clone and follow instructions to build UnrealGDAL from source. 16 | 17 | ## Usage 18 | 19 | Add ShpGeometry to `.uproject` or `.uplugin` 20 | 21 | ```json 22 | "Plugins": [ 23 | { 24 | "Name": "ShpGeometry", 25 | "Enabled": true 26 | } 27 | ] 28 | ``` 29 | 30 | Add build dependencies to your modules 31 | 32 | ```csharp 33 | PublicDependencyModuleNames.AddRange( 34 | new string[] 35 | { 36 | "ShpGeometry", 37 | "ShpGeometryEditor" 38 | } 39 | ); 40 | ``` 41 | 42 | ## Funding 43 | Development of this code was partially funded by the German Federal Ministry of Education and Research (BMBF) under funding reference number 13FH1I01IA. 44 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f7239efaeefbd82de33ebe18518e50de075ea4188a468a9e4991396433d2275f 3 | size 12699 4 | -------------------------------------------------------------------------------- /ShpGeometry.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 1, 4 | "VersionName": "0.0.1", 5 | "FriendlyName": "ShpGeometry", 6 | "Description": "Import shape files as geometry", 7 | "Category": "Other", 8 | "CreatedBy": "Iwer Petersen", 9 | "CreatedByURL": "https://github.com/iwer", 10 | "DocsURL": "", 11 | "MarketplaceURL": "", 12 | "SupportURL": "https://github.com/iwer/ShpGeometry", 13 | "CanContainContent": true, 14 | "IsBetaVersion": false, 15 | "IsExperimentalVersion": true, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "ShpGeometry", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default" 22 | }, 23 | { 24 | "Name": "ShpGeometryEditor", 25 | "Type": "Editor", 26 | "LoadingPhase": "PostEngineInit" 27 | } 28 | ], 29 | "Plugins": [ 30 | { 31 | "Name": "UnrealGDAL", 32 | "Enabled": true 33 | }, 34 | { 35 | "Name": "GeoReference", 36 | "Enabled": true 37 | }, 38 | { 39 | "Name": "SpatialGeometryTools", 40 | "Enabled": true 41 | }, 42 | { 43 | "Name": "ProceduralMeshComponent", 44 | "Enabled": true 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Private/ShpGeometryModule.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #include "ShpGeometryModule.h" 4 | #include "UnrealGDAL.h" 5 | #define LOCTEXT_NAMESPACE "FShpGeometryModule" 6 | 7 | void FShpGeometryModule::StartupModule() 8 | { 9 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 10 | FUnrealGDALModule* UnrealGDAL = FModuleManager::Get().LoadModulePtr("UnrealGDAL"); 11 | UnrealGDAL->InitGDAL(); 12 | } 13 | 14 | void FShpGeometryModule::ShutdownModule() 15 | { 16 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, 17 | // we call this function before unloading the module. 18 | } 19 | 20 | #undef LOCTEXT_NAMESPACE 21 | 22 | IMPLEMENT_MODULE(FShpGeometryModule, ShpGeometry) 23 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Private/ShpPolygonActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | 4 | #include "ShpPolygonActor.h" 5 | #include "PolygonHelper.h" 6 | 7 | // Sets default values 8 | AShpPolygonActor::AShpPolygonActor() 9 | { 10 | // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 11 | PrimaryActorTick.bCanEverTick = true; 12 | ProcMesh = CreateDefaultSubobject(TEXT("ProcMesh")); 13 | ProcMesh->SetupAttachment(GetRootComponent()); 14 | 15 | GeoLocation->bSnapToGround = true; 16 | } 17 | 18 | // Called when the game starts or when spawned 19 | void AShpPolygonActor::BeginPlay() 20 | { 21 | Super::BeginPlay(); 22 | 23 | } 24 | 25 | // Called every frame 26 | void AShpPolygonActor::Tick(float DeltaTime) 27 | { 28 | Super::Tick(DeltaTime); 29 | 30 | } 31 | 32 | void AShpPolygonActor::OnConstruction(const FTransform &Transform) 33 | { 34 | if(GeoLocation->GeoRef) { 35 | GeoLocation->Longitude = GeoLocation->GeoRef->Longitude; 36 | GeoLocation->Latitude = GeoLocation->GeoRef->Latitude; 37 | } 38 | else { 39 | UE_LOG(LogTemp, Warning, TEXT("AShpPolygonActor: Cant set Lon/Lat on GeolocationComponent, no GeoRef!")) 40 | } 41 | Super::OnConstruction(Transform); 42 | 43 | if (!GeoLocation->GeoRef) 44 | return; 45 | 46 | GeoLocation->UpdateParentActorLocation(); 47 | 48 | if(ShpFile) { 49 | ProcMesh->ClearAllMeshSections(); 50 | 51 | int polyIdx = 0; 52 | for (auto &polygon : ShpFile->Polygons) { 53 | 54 | float minZ = std::numeric_limits::max(); 55 | // transform vertices to game coordinates 56 | TArray < FVector > gameVerts; 57 | for (auto &v : polygon.Vertices) { 58 | FVector gv = GeoLocation->GeoRef->ToGameCoordinate(FVector(v.X, v.Y, v.Z)); 59 | 60 | 61 | // make relative to origin 62 | gv -= GetActorLocation(); 63 | gv.Z = 0;//GetActorLocation().Z; 64 | gameVerts.Add(gv); 65 | 66 | FVector groundVert = GeoLocation->SnapToGround(gv, 100); 67 | minZ = std::min(groundVert.Z - GetActorLocation().Z, minZ); 68 | } 69 | 70 | // set to min height 71 | // for(auto &v : gameVerts) { 72 | // v.Z = minZ; 73 | // } 74 | 75 | // earcut 76 | TArray < int32 > indices = PolygonHelper::TessellatePolygon(gameVerts, TArray(), true); 77 | 78 | // construct buffers 79 | TArray triIndices; 80 | TArray normals; 81 | TArray tangents; 82 | TArray texCoords; 83 | TArray colors; 84 | 85 | TArray normTriplet; 86 | normTriplet.Init(FVector(0,0,1),3); 87 | TArray tangTriplet; 88 | tangTriplet.Init(FProcMeshTangent(1,0,0),3); 89 | TArray colTriplet; 90 | colTriplet.Init(FLinearColor(0,0,0,1),3); 91 | 92 | int i = 0; 93 | while((i+3) <= indices.Num()) { 94 | triIndices.Add(indices[i+2]); 95 | triIndices.Add(indices[i+1]); 96 | triIndices.Add(indices[i]); 97 | normals.Append(normTriplet); 98 | tangents.Append(tangTriplet); 99 | colors.Append(colTriplet); 100 | i+=3; 101 | } 102 | 103 | texCoords = PolygonHelper::FlatUVMap(gameVerts); 104 | 105 | // add meshsection 106 | ProcMesh->CreateMeshSection_LinearColor(polyIdx, gameVerts, triIndices, normals, texCoords, colors, tangents, false); 107 | 108 | if(Material) 109 | ProcMesh->SetMaterial(polyIdx, Material); 110 | polyIdx++; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Public/ShpFileAsset.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/Object.h" 7 | #include "UObject/ObjectMacros.h" 8 | #include "ShpTypes/ShpPolygon.h" 9 | 10 | #include "ShpFileAsset.generated.h" 11 | /** 12 | * https://gdal.org/tutorials/vector_api_tut.html 13 | * https://www.esri.com/library/whitepapers/pdfs/shapefile.pdf 14 | */ 15 | UCLASS(BlueprintType, hidecategories=(Object)) 16 | class SHPGEOMETRY_API UShpFileAsset 17 | : public UDataAsset 18 | { 19 | GENERATED_BODY() 20 | public: 21 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere) 22 | TArray Polygons; 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Public/ShpGeometryModule.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | class FShpGeometryModule : public IModuleInterface 9 | { 10 | public: 11 | 12 | /** IModuleInterface implementation */ 13 | virtual void StartupModule() override; 14 | virtual void ShutdownModule() override; 15 | }; 16 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Public/ShpPolygonActor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Actor.h" 7 | #include "GeoLocatedActor.h" 8 | #include "ShpFileAsset.h" 9 | #include "ProceduralMeshComponent.h" 10 | 11 | #include "ShpPolygonActor.generated.h" 12 | 13 | UCLASS() 14 | class SHPGEOMETRY_API AShpPolygonActor : public AGeoLocatedActor 15 | { 16 | GENERATED_BODY() 17 | 18 | public: 19 | UPROPERTY(BlueprintReadWrite, EditAnywhere) 20 | UShpFileAsset * ShpFile; 21 | 22 | UPROPERTY(BlueprintReadWrite, EditAnywhere) 23 | UMaterialInterface * Material; 24 | 25 | UPROPERTY(BlueprintReadWrite, EditAnywhere) 26 | UProceduralMeshComponent *ProcMesh; 27 | 28 | // Sets default values for this actor's properties 29 | AShpPolygonActor(); 30 | 31 | protected: 32 | // Called when the game starts or when spawned 33 | virtual void BeginPlay() override; 34 | 35 | public: 36 | // Called every frame 37 | virtual void Tick(float DeltaTime) override; 38 | virtual void OnConstruction(const FTransform &Transform) override; 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /Source/ShpGeometry/Public/ShpTypes/ShpPolygon.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #pragma once 4 | #include "CoreMinimal.h" 5 | 6 | #include "ShpPolygon.generated.h" 7 | 8 | USTRUCT(Blueprintable, BlueprintType) 9 | struct FShpPolygon { 10 | GENERATED_BODY() 11 | 12 | UPROPERTY(BlueprintReadWrite, EditAnywhere) 13 | TArray Vertices; 14 | 15 | FShpPolygon() {} 16 | }; 17 | -------------------------------------------------------------------------------- /Source/ShpGeometry/ShpGeometry.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class ShpGeometry : ModuleRules 6 | { 7 | public ShpGeometry(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | } 15 | ); 16 | 17 | 18 | PrivateIncludePaths.AddRange( 19 | new string[] { 20 | // ... add other private include paths required here ... 21 | } 22 | ); 23 | 24 | 25 | PublicDependencyModuleNames.AddRange( 26 | new string[] 27 | { 28 | "Core", 29 | "GeoReference", 30 | "GDAL", 31 | "UnrealGDAL", 32 | "SpatialGeometryTools", 33 | "ProceduralMeshComponent" 34 | // ... add other public dependencies that you statically link with here ... 35 | } 36 | ); 37 | 38 | 39 | PrivateDependencyModuleNames.AddRange( 40 | new string[] 41 | { 42 | "CoreUObject", 43 | "Engine", 44 | "Slate", 45 | "SlateCore", 46 | // ... add private dependencies that you statically link with here ... 47 | } 48 | ); 49 | 50 | 51 | DynamicallyLoadedModuleNames.AddRange( 52 | new string[] 53 | { 54 | // ... add any modules that your module loads dynamically here ... 55 | } 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/AssetTools/ShpFileAssetActions.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | #include "ShpFileAssetActions.h" 3 | 4 | 5 | #include "Framework/MultiBox/MultiBoxBuilder.h" 6 | #include "ShpFileAsset.h" 7 | #include "Styling/SlateStyle.h" 8 | 9 | #define LOCTEXT_NAMESPACE "AssetTypeActions" 10 | 11 | FShpFileAssetActions::FShpFileAssetActions(const TSharedRef& InStyle) 12 | : Style(InStyle) 13 | {} 14 | 15 | bool FShpFileAssetActions::CanFilter() 16 | { 17 | return true; 18 | } 19 | 20 | void FShpFileAssetActions::GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) 21 | { 22 | FAssetTypeActions_Base::GetActions(InObjects, MenuBuilder); 23 | 24 | auto TextAssets = GetTypedWeakObjectPtrs(InObjects); 25 | 26 | MenuBuilder.AddMenuEntry( 27 | LOCTEXT("ShpFileAsset_DummyText", "Dummy Text"), 28 | LOCTEXT("ShpFileAsset_DummyTextToolTip", "Dummy menu entry."), 29 | FSlateIcon(), 30 | FUIAction( 31 | FExecuteAction::CreateLambda([=]{ 32 | 33 | }), 34 | FCanExecuteAction::CreateLambda([=] { 35 | return false; 36 | }) 37 | ) 38 | ); 39 | } 40 | 41 | uint32 FShpFileAssetActions::GetCategories() 42 | { 43 | return EAssetTypeCategories::Misc; 44 | } 45 | 46 | 47 | FText FShpFileAssetActions::GetName() const 48 | { 49 | return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ShpFileAsset", "ESRI Shape File Asset"); 50 | } 51 | 52 | 53 | UClass* FShpFileAssetActions::GetSupportedClass() const 54 | { 55 | return UShpFileAsset::StaticClass(); 56 | } 57 | 58 | 59 | FColor FShpFileAssetActions::GetTypeColor() const 60 | { 61 | return FColor::Blue; 62 | } 63 | 64 | 65 | bool FShpFileAssetActions::HasActions(const TArray& InObjects) const 66 | { 67 | return true; 68 | } 69 | 70 | 71 | 72 | #undef LOCTEXT_NAMESPACE 73 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/AssetTools/ShpFileAssetActions.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | #pragma once 3 | 4 | #include "AssetTypeActions_Base.h" 5 | #include "Templates/SharedPointer.h" 6 | 7 | class ISlateStyle; 8 | 9 | class FShpFileAssetActions 10 | : public FAssetTypeActions_Base 11 | { 12 | public: 13 | FShpFileAssetActions(const TSharedRef& InStyle); 14 | 15 | virtual bool CanFilter() override; 16 | virtual void GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) override; 17 | virtual uint32 GetCategories() override; 18 | virtual FText GetName() const override; 19 | virtual UClass* GetSupportedClass() const override; 20 | virtual FColor GetTypeColor() const override; 21 | virtual bool HasActions(const TArray& InObjects) const override; 22 | 23 | private: 24 | 25 | /** Pointer to the style set to use for toolkits. */ 26 | TSharedRef Style; 27 | }; 28 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/Factories/ShpFileAssetFactory.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | #include "ShpFileAssetFactory.h" 4 | #include "ShpFileAsset.h" 5 | #include "GDALHelpers.h" 6 | #include "GeoCoordinate.h" 7 | 8 | UShpFileAssetFactory::UShpFileAssetFactory(const FObjectInitializer& ObjectInitializer) 9 | { 10 | SupportedClass = UShpFileAsset::StaticClass(); 11 | bCreateNew = false; 12 | bEditorImport = true; 13 | Formats.Add(TEXT("shp;ESRI Shapefile")); 14 | } 15 | 16 | UObject* UShpFileAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled) 17 | { 18 | UShpFileAsset * Asset = NewObject(InParent, InClass, InName, Flags); 19 | 20 | // open file 21 | const GDALDatasetRef Gdaldata = GDALHelpers::OpenVector(Filename, true); 22 | if(!Gdaldata){ 23 | bOutOperationCanceled = true; 24 | return nullptr; 25 | } 26 | 27 | 28 | 29 | // get layers 30 | const int NumLayers = Gdaldata->GetLayerCount(); 31 | for(int i = 0; i < NumLayers; ++i) { 32 | OGRLayer * Layer = Gdaldata->GetLayer(i); 33 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: layer name %s"), ANSI_TO_TCHAR(Layer->GetName())); 34 | 35 | char * SrcWktStr = nullptr; 36 | Layer->GetSpatialRef()->exportToWkt(&SrcWktStr); 37 | FString SourceWkt = FString(SrcWktStr); 38 | FString TargetWkt = GDALHelpers::WktFromEPSG(UGeoCoordinate::EPSG_WGS84, false); 39 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: src: %s tgt: %s"), *SourceWkt, *TargetWkt); 40 | OGRCoordinateTransformationRef CoordTransform = GDALHelpers::CreateCoordinateTransform(SourceWkt, TargetWkt); 41 | if(!CoordTransform.IsValid()) { 42 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: CoordTransform invalid.")) 43 | } 44 | 45 | Layer->ResetReading(); 46 | for(auto &Feature : Layer) { 47 | for( const auto& OField: *Feature ) 48 | { 49 | switch( OField.GetType() ) 50 | { 51 | case OFTInteger: 52 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Field %s: %d,"), ANSI_TO_TCHAR(OField.GetName()) ,OField.GetInteger() ); 53 | break; 54 | case OFTReal: 55 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Field %s: %.3f,"), ANSI_TO_TCHAR(OField.GetName()) ,OField.GetDouble() ); 56 | break; 57 | case OFTString: 58 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Field %s: %s,"), ANSI_TO_TCHAR(OField.GetName()) ,OField.GetString() ); 59 | break; 60 | default: 61 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Field %s: %s,"), ANSI_TO_TCHAR(OField.GetName()) ,OField.GetAsString() ); 62 | break; 63 | } 64 | } 65 | 66 | 67 | const int NumGeom = Feature->GetGeomFieldCount(); 68 | for(int j = 0; j < NumGeom; ++j) { 69 | OGRGeometry* Geometry = Feature->GetGeomFieldRef(j); 70 | if(Geometry != nullptr) { 71 | if(wkbFlatten(Geometry->getGeometryType()) == wkbPoint){ 72 | UE_LOG(LogTemp,Warning,TEXT("UShpFileAssetFactory: Point geometry")) 73 | } 74 | else if (wkbFlatten(Geometry->getGeometryType()) == wkbLineString) { 75 | UE_LOG(LogTemp,Warning,TEXT("UShpFileAssetFactory: LineString geometry")) 76 | } 77 | else if (wkbFlatten(Geometry->getGeometryType()) == wkbPolygon) { 78 | UE_LOG(LogTemp,Warning,TEXT("UShpFileAssetFactory: Polygon geometry")) 79 | const auto Polygon = Geometry->toPolygon(); 80 | 81 | OGRLinearRing * Exterior = Polygon->getExteriorRing(); 82 | 83 | // fix order if necessary 84 | if(!Exterior->isClockwise()) { 85 | Exterior->reverseWindingOrder(); 86 | } 87 | 88 | FShpPolygon ShpPolygon; 89 | 90 | for(auto &Point : Exterior) { 91 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Point X:%.3f Y:%.3f"), Point.getX(), Point.getY()); 92 | FVector In(Point.getX(), Point.getY(),0); 93 | FVector Out; 94 | if(GDALHelpers::TransformCoordinate(CoordTransform, In, Out)) { 95 | UE_LOG(LogTemp, Warning, TEXT("UShpFileAssetFactory: Transformed Point X:%.3f Y:%.3f"), Out.X, Out.Y); 96 | ShpPolygon.Vertices.Add(Out); 97 | } 98 | } 99 | 100 | if(ShpPolygon.Vertices.Num() > 0) 101 | Asset->Polygons.Add(ShpPolygon); 102 | } 103 | else if (wkbFlatten(Geometry->getGeometryType()) == wkbMultiPoint) { 104 | UE_LOG(LogTemp,Warning,TEXT("UShpFileAssetFactory: MultiPoint geometry")) 105 | } 106 | else if (wkbFlatten(Geometry->getGeometryType()) == wkbMultiPolygon) { 107 | UE_LOG(LogTemp,Warning,TEXT("UShpFileAssetFactory: MultiPolygon geometry")) 108 | } 109 | } 110 | } 111 | 112 | } 113 | } 114 | 115 | 116 | return Asset; 117 | } 118 | 119 | bool UShpFileAssetFactory::FactoryCanImport(const FString & Filename) 120 | { 121 | return true; 122 | } 123 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/Factories/ShpFileAssetFactory.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | #pragma once 3 | 4 | #include "Factories/Factory.h" 5 | #include "UObject/ObjectMacros.h" 6 | 7 | #include "ShpFileAssetFactory.generated.h" 8 | 9 | UCLASS(BlueprintType, hidecategories=Object) 10 | class UShpFileAssetFactory 11 | : public UFactory 12 | { 13 | GENERATED_BODY() 14 | public: 15 | UShpFileAssetFactory(const FObjectInitializer& ObjectInitializer); 16 | virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled) override; 17 | virtual bool FactoryCanImport(const FString & Filename) override; 18 | }; 19 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/ShpGeometryEditorModule.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | 4 | #include "CoreMinimal.h" 5 | #include "Modules/ModuleManager.h" 6 | #include "UnrealGDAL.h" 7 | 8 | #include "AssetTools/ShpFileAssetActions.h" 9 | #include "Styles/ShpFileAssetEditorStyle.h" 10 | 11 | #define LOCTEXT_NAMESPACE "FShpGeometryEditorModule" 12 | 13 | 14 | class FShpGeometryEditorModule : public IModuleInterface 15 | { 16 | public: 17 | 18 | /** IModuleInterface implementation */ 19 | virtual void StartupModule() override 20 | { 21 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module 22 | FUnrealGDALModule* UnrealGDAL = FModuleManager::Get().LoadModulePtr("UnrealGDAL"); 23 | UnrealGDAL->InitGDAL(); 24 | 25 | Style = MakeShareable(new FShpFileAssetEditorStyle()); 26 | 27 | RegisterAssetTools(); 28 | } 29 | 30 | virtual void ShutdownModule() override 31 | { 32 | UnregisterAssetTools(); 33 | } 34 | 35 | virtual bool SupportsDynamicReloading() override 36 | { 37 | return true; 38 | } 39 | protected: 40 | /** Registers asset tool actions. */ 41 | void RegisterAssetTools() 42 | { 43 | IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); 44 | TSharedPtr ShpFileAction = MakeShareable(new FShpFileAssetActions(Style.ToSharedRef())); 45 | RegisterAssetTypeAction(AssetTools, ShpFileAction.ToSharedRef()); 46 | 47 | } 48 | 49 | /** 50 | * Registers a single asset type action. 51 | * 52 | * @param AssetTools The asset tools object to register with. 53 | * @param Action The asset type action to register. 54 | */ 55 | void RegisterAssetTypeAction(IAssetTools& AssetTools, TSharedRef Action) 56 | { 57 | AssetTools.RegisterAssetTypeActions(Action); 58 | RegisteredAssetTypeActions.Add(Action); 59 | } 60 | 61 | /** Unregisters asset tool actions. */ 62 | void UnregisterAssetTools() 63 | { 64 | FAssetToolsModule* AssetToolsModule = FModuleManager::GetModulePtr("AssetTools"); 65 | 66 | if (AssetToolsModule) 67 | { 68 | IAssetTools& AssetTools = AssetToolsModule->Get(); 69 | 70 | for (auto Action : RegisteredAssetTypeActions) 71 | { 72 | AssetTools.UnregisterAssetTypeActions(Action); 73 | } 74 | } 75 | } 76 | 77 | private: 78 | /** The collection of registered asset type actions. */ 79 | TArray> RegisteredAssetTypeActions; 80 | /** Holds the plug-ins style set. */ 81 | TSharedPtr Style; 82 | }; 83 | 84 | IMPLEMENT_MODULE(FShpGeometryEditorModule, ShpGeometryEditor); 85 | #undef LOCTEXT_NAMESPACE 86 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/Private/Styles/ShpFileAssetEditorStyle.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | #pragma once 3 | 4 | #include "Interfaces/IPluginManager.h" 5 | #include "Brushes/SlateImageBrush.h" 6 | #include "Styling/SlateStyle.h" 7 | #include "Styling/SlateStyleRegistry.h" 8 | 9 | #define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__) 10 | #define BOX_BRUSH(RelativePath, ...) FSlateBoxBrush(RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__) 11 | #define BORDER_BRUSH(RelativePath, ...) FSlateBorderBrush(RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__) 12 | #define TTF_FONT(RelativePath, ...) FSlateFontInfo(RootToContentDir(RelativePath, TEXT(".ttf")), __VA_ARGS__) 13 | #define OTF_FONT(RelativePath, ...) FSlateFontInfo(RootToContentDir(RelativePath, TEXT(".otf")), __VA_ARGS__) 14 | 15 | 16 | /** 17 | * Implements the visual style of the text asset editor UI. 18 | */ 19 | class FShpFileAssetEditorStyle 20 | : public FSlateStyleSet 21 | { 22 | public: 23 | 24 | /** Default constructor. */ 25 | FShpFileAssetEditorStyle() 26 | : FSlateStyleSet("ShpFileAssetEditorStyle") 27 | { 28 | const FVector2D Icon16x16(16.0f, 16.0f); 29 | const FVector2D Icon20x20(20.0f, 20.0f); 30 | const FVector2D Icon40x40(40.0f, 40.0f); 31 | 32 | const FString BaseDir = IPluginManager::Get().FindPlugin("ShpGeometry")->GetBaseDir(); 33 | SetContentRoot(BaseDir / TEXT("Content")); 34 | 35 | // set new styles here, for example... 36 | //Set("TextAssetEditor.FancyButton", new IMAGE_BRUSH("icon_forward_40x", Icon40x40)); 37 | 38 | FSlateStyleRegistry::RegisterSlateStyle(*this); 39 | } 40 | 41 | /** Destructor. */ 42 | ~FShpFileAssetEditorStyle() 43 | { 44 | FSlateStyleRegistry::UnRegisterSlateStyle(*this); 45 | } 46 | }; 47 | 48 | 49 | #undef IMAGE_BRUSH 50 | #undef BOX_BRUSH 51 | #undef BORDER_BRUSH 52 | #undef TTF_FONT 53 | #undef OTF_FONT 54 | -------------------------------------------------------------------------------- /Source/ShpGeometryEditor/ShpGeometryEditor.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Iwer Petersen. All rights reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class ShpGeometryEditor : ModuleRules 6 | { 7 | public ShpGeometryEditor(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicIncludePaths.AddRange( 12 | new string[] { 13 | // ... add public include paths required here ... 14 | }); 15 | 16 | 17 | PrivateIncludePaths.AddRange( 18 | new string[] { 19 | // ... add other private include paths required here ... 20 | "ShpGeometryEditor/Private", 21 | "ShpGeometryEditor/Private/Factories", 22 | "ShpGeometryEditor/Private/AssetTools", 23 | "ShpGeometryEditor/Private/Styles" 24 | }); 25 | 26 | 27 | PrivateDependencyModuleNames.AddRange( 28 | new string[] 29 | { 30 | // ... add private dependencies that you statically link with here ... 31 | "ContentBrowser", 32 | "Core", 33 | "CoreUObject", 34 | "DesktopWidgets", 35 | "EditorStyle", 36 | "Engine", 37 | "InputCore", 38 | "Projects", 39 | "RenderCore", 40 | "Slate", 41 | "SlateCore", 42 | "UnrealEd", 43 | "GDAL", 44 | "UnrealGDAL", 45 | "GeoReference", 46 | "ShpGeometry" 47 | }); 48 | 49 | 50 | DynamicallyLoadedModuleNames.AddRange( 51 | new string[] 52 | { 53 | // ... add any modules that your module loads dynamically here ... 54 | "AssetTools", 55 | "MainFrame" 56 | }); 57 | 58 | PrivateIncludePathModuleNames.AddRange( 59 | new string[] { 60 | "AssetTools", 61 | "UnrealEd" 62 | }); 63 | } 64 | } 65 | --------------------------------------------------------------------------------