void FShaderResource::InitRHI()
{
	checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data."));

	// we can't have this called on the wrong platform's shaders
	if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform))
 	{
 		if (FPlatformProperties::RequiresCookedData())
 		{
 			UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), 
				*LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString());
 		}
 		return;
 	}

	INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1);
	SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime);

	FShaderCache* ShaderCache = FShaderCache::GetShaderCache();

	if(Target.Frequency == SF_Vertex)
	{
		VertexShader = ShaderCache ? ShaderCache->GetVertexShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateVertexShader(Code);
	}
	else if(Target.Frequency == SF_Pixel)
	{
		PixelShader = ShaderCache ? ShaderCache->GetPixelShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreatePixelShader(Code);
	}
	else if(Target.Frequency == SF_Hull)
	{
		HullShader = ShaderCache ? ShaderCache->GetHullShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateHullShader(Code);
	}
	else if(Target.Frequency == SF_Domain)
	{
		DomainShader = ShaderCache ? ShaderCache->GetDomainShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateDomainShader(Code);
	}
	else if(Target.Frequency == SF_Geometry)
	{
		if (SpecificType)
		{
			FStreamOutElementList ElementList;
			TArray<uint32> StreamStrides;
			int32 RasterizedStream = -1;
			SpecificType->GetStreamOutElements(ElementList, StreamStrides, RasterizedStream);
			checkf(ElementList.Num(), *FString::Printf(TEXT("Shader type %s was given GetStreamOutElements implementation that had no elements!"), SpecificType->GetName()));

			//@todo - not using the cache
			GeometryShader = RHICreateGeometryShaderWithStreamOutput(Code, ElementList, StreamStrides.Num(), StreamStrides.GetData(), RasterizedStream);
		}
		else
		{
			GeometryShader = ShaderCache ? ShaderCache->GetGeometryShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateGeometryShader(Code);
		}
	}
	else if(Target.Frequency == SF_Compute)
	{
		ComputeShader = ShaderCache ? ShaderCache->GetComputeShader((EShaderPlatform)Target.Platform, Code) : RHICreateComputeShader(Code);
	}

	if (Target.Frequency != SF_Geometry)
	{
		checkf(!SpecificType, *FString::Printf(TEXT("Only geometry shaders can use GetStreamOutElements, shader type %s"), SpecificType->GetName()));
	}

	if (!FPlatformProperties::HasEditorOnlyData())
	{
		DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num());
		DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize());
		Code.Empty();
	}
}
Example #2
0
void FCanvasItemTestbed::Draw( class FViewport* Viewport, class FCanvas* Canvas )
{
	bTestState = !bTestState;

	if( !bShowTestbed )
	{
		return;
	}

	
	// A little ott for a testbed - but I wanted to draw several lines to ensure it worked :)
	if( TestLine.bTestSet == false )
	{
		TestLine.bTestSet = true;
		TestLine.LineStart.X = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().X );
		TestLine.LineStart.Y = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().Y );
		TestLine.LineEnd.X = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().X );
		TestLine.LineEnd.Y  = FMath::FRandRange( 0.0f, Viewport->GetSizeXY().Y );
		TestLine.LineMove.X = FMath::FRandRange( 0.0f, 32.0f );
		TestLine.LineMove.Y = FMath::FRandRange( 0.0f, 32.0f );
		TestLine.LineMove2.X = FMath::FRandRange( 0.0f, 32.0f );
		TestLine.LineMove2.Y = FMath::FRandRange( 0.0f, 32.0f );
	}
	else
	{
		TestLine.LineStart += TestLine.LineMove;
		TestLine.LineEnd += TestLine.LineMove2;
		if( TestLine.LineStart.X < 0 )
		{
			TestLine.LineMove.X = -TestLine.LineMove.X;
		}
		if( TestLine.LineStart.Y < 0 )
		{
			TestLine.LineMove.Y = -TestLine.LineMove.Y;
		}
		if( TestLine.LineEnd.X < 0 )
		{
			TestLine.LineMove2.X = -TestLine.LineMove2.X;
		}
		if( TestLine.LineEnd.Y < 0 )
		{
			TestLine.LineMove2.Y = -TestLine.LineMove2.Y;
		}
		if( TestLine.LineStart.X > Viewport->GetSizeXY().X )
		{
			TestLine.LineMove.X = -TestLine.LineMove.X;
		}
		if( TestLine.LineStart.Y > Viewport->GetSizeXY().Y )
		{
			TestLine.LineMove.Y = -TestLine.LineMove.Y;
		}
		if( TestLine.LineEnd.X > Viewport->GetSizeXY().X )
		{
			TestLine.LineMove2.X = -TestLine.LineMove2.X;
		}
		if( TestLine.LineEnd.Y > Viewport->GetSizeXY().Y )
		{
			TestLine.LineMove2.Y = -TestLine.LineMove2.Y;
		}
	}
	
	// Text
	float CenterX = 0.0f;
	float YTest = 16.0f;
	FCanvasTextItem TextItem( FVector2D( CenterX, YTest ), LOCTEXT( "stringhere", "String Here" ), GEngine->GetSmallFont(), FLinearColor::Red );	
	TextItem.Draw( Canvas );
	
	// Shadowed text
	TextItem.Position.Y += TextItem.DrawnSize.Y;
	TextItem.Scale.X = 2.0f;
	TextItem.EnableShadow( FLinearColor::Green, FVector2D( 2.0f, 2.0f ) );
	TextItem.Text = LOCTEXT( "Scaled String here", "Scaled String here" );
	TextItem.Draw( Canvas );
	TextItem.DisableShadow();

	TextItem.Position.Y += TextItem.DrawnSize.Y;;
	TextItem.Text = LOCTEXT( "CenterdStringhere", "CenterdStringhere" );
	TextItem.Scale.X = 1.0f;
	TextItem.bCentreX = true;
	TextItem.Draw( Canvas );

	// Outlined text
	TextItem.Position.Y += TextItem.DrawnSize.Y;
	TextItem.Text = LOCTEXT( "ScaledCentredStringhere", "Scaled Centred String here" );	
	TextItem.OutlineColor = FLinearColor::Black;
	TextItem.bOutlined = true;
	TextItem.Scale = FVector2D( 2.0f, 2.0f );
	TextItem.SetColor( FLinearColor::Green );
	TextItem.Text = LOCTEXT( "ScaledCentredOutlinedStringhere", "Scaled Centred Outlined String here" );	
	TextItem.Draw( Canvas );
	
	// a line
	FCanvasLineItem LineItem( TestLine.LineStart, TestLine.LineEnd );
	LineItem.Draw( Canvas );

	// some boxes
	FCanvasBoxItem BoxItem( FVector2D( 88.0f, 88.0f ), FVector2D( 188.0f, 188.0f ) );
	BoxItem.SetColor( FLinearColor::Yellow );
	BoxItem.Draw( Canvas );

	BoxItem.SetColor( FLinearColor::Red );
	BoxItem.Position = FVector2D( 256.0f, 256.0f );
	BoxItem.Draw( Canvas );

	BoxItem.SetColor( FLinearColor::Blue );
	BoxItem.Position = FVector2D( 6.0f, 6.0f );
	BoxItem.Size = FVector2D( 48.0f, 96.0f );
	BoxItem.Draw( Canvas );
	
	// Triangle
	FCanvasTriangleItem TriItem(  FVector2D( 48.0f, 48.0f ), FVector2D( 148.0f, 48.0f ), FVector2D( 48.0f, 148.0f ), GWhiteTexture );
	TriItem.Draw( Canvas );

	// Triangle list
	TArray< FCanvasUVTri >	TriangleList;
	FCanvasUVTri SingleTri;
	SingleTri.V0_Pos = FVector2D( 128.0f, 128.0f );
	SingleTri.V1_Pos = FVector2D( 248.0f, 108.0f );
	SingleTri.V2_Pos = FVector2D( 100.0f, 348.0f );
	SingleTri.V0_UV = FVector2D::ZeroVector;
	SingleTri.V1_UV = FVector2D::ZeroVector;
	SingleTri.V2_UV = FVector2D::ZeroVector;
	TriangleList.Add( SingleTri );
	SingleTri.V0_Pos = FVector2D( 348.0f, 128.0f );
	SingleTri.V1_Pos = FVector2D( 448.0f, 148.0f );
	SingleTri.V2_Pos = FVector2D( 438.0f, 308.0f );
	TriangleList.Add( SingleTri );

	FCanvasTriangleItem TriItemList( TriangleList, GWhiteTexture );
	TriItemList.SetColor( FLinearColor::Red );
	TriItemList.Draw( Canvas );
	
// 	FCanvasNGonItem NGon( FVector2D( 256.0f, 256.0f ), FVector2D( 256.0f, 256.0f ), 6, GWhiteTexture, FLinearColor::White );
// 	NGon.Draw( Canvas );
// 
// 	FCanvasNGonItem NGon2( FVector2D( 488, 666.0f ), FVector2D( 256.0f, 256.0f ), 16, GWhiteTexture, FLinearColor::Green );
// 	NGon2.Draw( Canvas );

	// Texture
	UTexture* SelectedTexture = GEditor->GetSelectedObjects()->GetTop<UTexture>();	
	if( SelectedTexture )
	{
		// Plain tex
		FCanvasTileItem TileItem( FVector2D( 128.0f,128.0f ), SelectedTexture->Resource, FLinearColor::White );
		TileItem.Draw( Canvas );
		TileItem.Size = FVector2D( 32.0f,32.0f );
		TileItem.Position = FVector2D( 16.0f,16.0f );
		TileItem.Draw( Canvas );

		// UV 
		TileItem.Size = FVector2D( 64.0f,64.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( 1.0f, 1.0f );
		TileItem.Position = FVector2D( 256.0f,16.0f );
		TileItem.Draw( Canvas );

		// UV 
		TileItem.Size = FVector2D( 64.0f,64.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( 1.0f, -1.0f );
		TileItem.Position = FVector2D( 356.0f,16.0f );
		TileItem.Draw( Canvas );

		// UV 
		TileItem.Size = FVector2D( 64.0f,64.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( -1.0f, 1.0f );
		TileItem.Position = FVector2D( 456.0f,16.0f );
		TileItem.Draw( Canvas );

		// UV 
		TileItem.Size = FVector2D( 64.0f,64.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( -1.0f, -1.0f );
		TileItem.Position = FVector2D( 556.0f,16.0f );
		TileItem.Draw( Canvas );

		// Rotate top/left pivot
		TileItem.Size = FVector2D( 96.0f,96.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( 1.0f, 1.0f );
		TileItem.Position = FVector2D( 400.0f,264.0f );
		TileItem.Rotation.Yaw = TestLine.Testangle;
		TileItem.Draw( Canvas );

		// Rotate center pivot
		TileItem.Size = FVector2D( 128.0f, 128.0f );
		TileItem.UV0 = FVector2D( 0.0f, 0.0f );
		TileItem.UV1 = FVector2D( 1.0f, 1.0f );
		TileItem.Position = FVector2D( 600.0f,264.0f );
		TileItem.Rotation.Yaw = 360.0f - TestLine.Testangle;
		TileItem.PivotPoint = FVector2D( 0.5f, 0.5f );
		TileItem.Draw( Canvas );

		TestLine.Testangle = FMath::Fmod( TestLine.Testangle + 2.0f, 360.0f );

		// textured tri
		FCanvasTriangleItem TriItemTex(  FVector2D( 48.0f, 48.0f ), FVector2D( 148.0f, 48.0f ), FVector2D( 48.0f, 148.0f ), FVector2D( 0.0f, 0.0f ), FVector2D( 1.0f, 0.0f ), FVector2D( 0.0f, 1.0f ), SelectedTexture->Resource  );
		TriItem.Texture = GWhiteTexture;
		TriItemTex.Draw( Canvas );

		// moving tri (only 1 point moves !)
		TriItemTex.Position = TestLine.LineStart;
		TriItemTex.Draw( Canvas );
	}
}
Example #3
0
void CCompositeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage)

//	GetImage
//
//	Fills in the image

	{
	int i;

	//	Null case

	if (m_Layers.GetCount() == 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	//	Get all the layers

	TArray<CObjectImageArray> Result;
	Result.InsertEmpty(m_Layers.GetCount());
	for (i = 0; i < m_Layers.GetCount(); i++)
		m_Layers[i]->GetImage(Selector, &Result[i]);

	//	Create the composited image
	//
	//	First we need to determine the size of the final image, based
	//	on the size and position of each layer.

	int xMin = 0;
	int xMax = 0;
	int yMin = 0;
	int yMax = 0;

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		int xImageOffset = 0;
		int yImageOffset = 0;

		int xMaxImage = (RectWidth(rcRect) / 2) + xImageOffset;
		int xMinImage = xMaxImage - RectWidth(rcRect);
		int yMaxImage = (RectHeight(rcRect) / 2) + yImageOffset;
		int yMinImage = yMaxImage - RectHeight(rcRect);

		xMin = Min(xMin, xMinImage);
		xMax = Max(xMax, xMaxImage);
		yMin = Min(yMin, yMinImage);
		yMax = Max(yMax, yMaxImage);
		}

	//	Create destination image

	int cxWidth = xMax - xMin;
	int cyHeight = yMax - yMin;
	if (cxWidth <= 0 || cyHeight <= 0)
		{
		*retImage = EMPTY_IMAGE;
		return;
		}

	CG32bitImage *pComp = new CG32bitImage;
	pComp->Create(cxWidth, cyHeight, CG32bitImage::alpha1);

	int xCenter = cxWidth / 2;
	int yCenter = cyHeight / 2;

	//	Blt on the destination

	for (i = 0; i < m_Layers.GetCount(); i++)
		{
		CObjectImageArray &LayerImage = Result[i];
		const RECT &rcRect = LayerImage.GetImageRect();

		//	Paint the image

		LayerImage.PaintImage(*pComp,
				xCenter,
				yCenter,
				0,
				0);
		}

	//	Initialize an image

	RECT rcFinalRect;
	rcFinalRect.left = 0;
	rcFinalRect.top = 0;
	rcFinalRect.right = cxWidth;
	rcFinalRect.bottom = cyHeight;

	CObjectImageArray Comp;
	Comp.Init(pComp, rcFinalRect, 0, 0, true);

	//	Done

	retImage->TakeHandoff(Comp);
	}
void FGameplayDebuggerShape::Draw(UWorld* World, FGameplayDebuggerCanvasContext& Context)
{
	FVector DescLocation;
	switch (Type)
	{
	case EGameplayDebuggerShape::Point:
		if (ShapeData.Num() == 2 && ShapeData[1].X > 0)
		{
			DrawDebugSphere(World, ShapeData[0], ShapeData[1].X, 16, Color);
			DescLocation = ShapeData[0];
		}
		break;

	case EGameplayDebuggerShape::Segment:
		if (ShapeData.Num() == 3 && ShapeData[2].X > 0)
		{
			DrawDebugLine(World, ShapeData[0], ShapeData[1], Color, false, -1.0f, 0, ShapeData[2].X);
			DescLocation = (ShapeData[0] + ShapeData[1]) * 0.5f;
		}
		break;

	case EGameplayDebuggerShape::Box:
		if (ShapeData.Num() == 2)
		{
			DrawDebugBox(World, ShapeData[0], ShapeData[1], Color);
			DescLocation = ShapeData[0];
		}
		break;

	case EGameplayDebuggerShape::Cone:
		if (ShapeData.Num() == 3 && ShapeData[2].X > 0)
		{
			DrawDebugCone(World, ShapeData[0], ShapeData[1], ShapeData[2].X, PI * 0.5f, PI * 0.5f, 16, Color);
			DescLocation = ShapeData[0];
		}
		break;

	case EGameplayDebuggerShape::Cylinder:
		if (ShapeData.Num() == 2)
		{
			DrawDebugCylinder(World, ShapeData[0] - FVector(0, 0, ShapeData[1].Z), ShapeData[0] + FVector(0, 0, ShapeData[1].Z), ShapeData[1].X, 16, Color);
			DescLocation = ShapeData[0];
		}
		break;

	case EGameplayDebuggerShape::Capsule:
		if (ShapeData.Num() == 2)
		{
			DrawDebugCapsule(World, ShapeData[0], ShapeData[1].Z, ShapeData[1].X, FQuat::Identity, Color);
			DescLocation = ShapeData[0];
		}
		break;

	case EGameplayDebuggerShape::Polygon:
		if (ShapeData.Num() > 0)
		{
			FVector MidPoint = FVector::ZeroVector;
			TArray<int32> Indices;
			for (int32 Idx = 0; Idx < ShapeData.Num(); Idx++)
			{
				Indices.Add(Idx);
				MidPoint += ShapeData[Idx];
			}

			DrawDebugMesh(World, ShapeData, Indices, Color);
			DescLocation = MidPoint / ShapeData.Num();
		}
		break;

	default:
		break;
	}

	if (Description.Len() && Context.IsLocationVisible(DescLocation))
	{
		const FVector2D ScreenLoc = Context.ProjectLocation(DescLocation);
		Context.PrintAt(ScreenLoc.X, ScreenLoc.Y, Color, Description);
	}
}
Example #5
0
void InitThingdef()
{
	// Sort the flag lists
	for (size_t i = 0; i < NUM_FLAG_LISTS; ++i)
	{
		qsort (FlagLists[i].Defs, FlagLists[i].NumDefs, sizeof(FFlagDef), flagcmp);
	}

	// Create a sorted list of properties
	if (properties.Size() == 0)
	{
		FAutoSegIterator probe(GRegHead, GRegTail);

		while (*++probe != NULL)
		{
			properties.Push((FPropertyInfo *)*probe);
		}
		properties.ShrinkToFit();
		qsort(&properties[0], properties.Size(), sizeof(properties[0]), propcmp);
	}

	// Create a sorted list of native action functions
	if (AFTable.Size() == 0)
	{
		FAutoSegIterator probe(ARegHead, ARegTail);

		while (*++probe != NULL)
		{
			AFTable.Push(*(AFuncDesc *)*probe);
		}
		AFTable.ShrinkToFit();
		qsort(&AFTable[0], AFTable.Size(), sizeof(AFTable[0]), funccmp);
	}

	// Create a sorted list of native variables
	if (variables.Size() == 0)
	{
		FAutoSegIterator probe(MRegHead, MRegTail);

		while (*++probe != NULL)
		{
			variables.Push((FVariableInfo *)*probe);
		}
		variables.ShrinkToFit();
		qsort(&variables[0], variables.Size(), sizeof(variables[0]), varcmp);
	}
}
void SPropertyEditorAsset::OnGetAllowedClasses(TArray<const UClass*>& AllowedClasses)
{
	AllowedClasses.Add(ObjectClass);
}
Example #7
0
void SGridPanel::OnArrangeChildren( const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren ) const
{
    // PREPARE PHASE
    // Prepare some data for arranging children.
    // FinalColumns will be populated with column sizes that include the stretched column sizes.
    // Then we will build partial sums so that we can easily handle column spans.
    // Repeat the same for rows.

    float ColumnCoeffTotal = 0.0f;
    TArray<float> FinalColumns;
    if ( Columns.Num() > 0 )
    {
        FinalColumns.AddUninitialized(Columns.Num());
        FinalColumns[FinalColumns.Num()-1] = 0.0f;
    }

    float RowCoeffTotal = 0.0f;
    TArray<float> FinalRows;
    if ( Rows.Num() > 0 )
    {
        FinalRows.AddUninitialized(Rows.Num());
        FinalRows[FinalRows.Num()-1] = 0.0f;
    }

    CalculateStretchedCellSizes(FinalColumns, AllottedGeometry.Size.X, Columns, ColFillCoefficients);
    CalculateStretchedCellSizes(FinalRows, AllottedGeometry.Size.Y, Rows, RowFillCoefficients);

    // Build up partial sums for row and column sizes so that we can handle column and row spans conveniently.
    ComputePartialSums(FinalColumns);
    ComputePartialSums(FinalRows);

    // ARRANGE PHASE
    for( int32 SlotIndex=0; SlotIndex < Slots.Num(); ++SlotIndex )
    {
        const FSlot& CurSlot = Slots[SlotIndex];
        const EVisibility ChildVisibility = CurSlot.GetWidget()->GetVisibility();
        if ( ArrangedChildren.Accepts(ChildVisibility) )
        {
            // Figure out the position of this cell.
            const FVector2D ThisCellOffset( FinalColumns[CurSlot.ColumnParam], FinalRows[CurSlot.RowParam] );
            // Figure out the size of this slot; takes row span into account.
            // We use the properties of partial sums arrays to achieve this.
            const FVector2D CellSize(
                FinalColumns[CurSlot.ColumnParam+CurSlot.ColumnSpanParam] - ThisCellOffset.X ,
                FinalRows[CurSlot.RowParam+CurSlot.RowSpanParam] - ThisCellOffset.Y );

            // Do the standard arrangement of elements within a slot
            // Takes care of alignment and padding.
            const FMargin SlotPadding(CurSlot.SlotPadding.Get());
            AlignmentArrangeResult XAxisResult = AlignChild<Orient_Horizontal>( CellSize.X, CurSlot, SlotPadding );
            AlignmentArrangeResult YAxisResult = AlignChild<Orient_Vertical>( CellSize.Y, CurSlot, SlotPadding );

            // Output the result
            ArrangedChildren.AddWidget( ChildVisibility, AllottedGeometry.MakeChild(
                                            CurSlot.GetWidget(),
                                            ThisCellOffset + FVector2D( XAxisResult.Offset, YAxisResult.Offset ) + CurSlot.NudgeParam,
                                            FVector2D(XAxisResult.Size, YAxisResult.Size)
                                        ));
        }
    }
}
Example #8
0
//------------------------------------------------------------------------------
bool FStructScriptLoader::LoadStructWithScript(UStruct* DestScriptContainer, FArchive& Ar, bool bAllowDeferredSerialization)
{
	if (!Ar.IsLoading() || !IsPrimed() || GIsDuplicatingClassForReinstancing)
	{
		return false;
	}

	bool const bIsLinkerLoader = Ar.IsPersistent() && (Ar.GetLinker() != nullptr);
	int32 const ScriptEndOffset = ScriptSerializationOffset + SerializedScriptSize;

	// to help us move development forward (and not have to support ancient 
	// script code), we define a minimum script version
	bool bSkipScriptSerialization = (Ar.UE4Ver() < VER_MIN_SCRIPTVM_UE4) || (Ar.LicenseeUE4Ver() < VER_MIN_SCRIPTVM_LICENSEEUE4);
#if WITH_EDITOR
	static const FBoolConfigValueHelper SkipByteCodeHelper(TEXT("StructSerialization"), TEXT("SkipByteCodeSerialization"));
	// in editor builds, we're going to regenerate the bytecode anyways, so it
	// is a waste of cycles to try and serialize it in
	bSkipScriptSerialization |= (bool)SkipByteCodeHelper;
#endif // WITH_EDITOR
	bSkipScriptSerialization &= bIsLinkerLoader; // to keep consistent with old UStruct::Serialize() functionality

	if (bSkipScriptSerialization)
	{
		int32 TrackedBufferSize = BytecodeBufferSize;
		BytecodeBufferSize = 0; // temporarily clear so that ClearScriptCode() doesn't leave Class->Script with anything allocated
		ClearScriptCode(DestScriptContainer);
		BytecodeBufferSize = TrackedBufferSize;

		// we have to at least move the archiver forward, so it is positioned 
		// where it expects to be (as if we read in the script)
		Ar.Seek(ScriptEndOffset);
		return false;
	}

	bAllowDeferredSerialization &= bIsLinkerLoader;
	if (bAllowDeferredSerialization && ShouldDeferScriptSerialization(Ar))
	{
		ULinkerLoad* Linker = CastChecked<ULinkerLoad>(Ar.GetLinker());
		FDeferredScriptTracker::Get().AddDeferredScriptObject(Linker, DestScriptContainer, *this);

		// we have to at least move the archiver forward, so it is positioned 
		// where it expects to be (as if we read in the script)
		Ar.Seek(ScriptEndOffset);
		return false;
	}

	Ar.Seek(ScriptSerializationOffset);
	if (bIsLinkerLoader)
	{
		ULinkerLoad* LinkerLoad = CastChecked<ULinkerLoad>(Ar.GetLinker());

		TArray<uint8> ShaScriptBuffer;
		ShaScriptBuffer.AddUninitialized(SerializedScriptSize);

		Ar.Serialize(ShaScriptBuffer.GetData(), SerializedScriptSize);
		ensure(ScriptEndOffset == Ar.Tell());
		LinkerLoad->UpdateScriptSHAKey(ShaScriptBuffer);

		Ar.Seek(ScriptSerializationOffset);
	}

	DestScriptContainer->Script.Empty(BytecodeBufferSize);
	DestScriptContainer->Script.AddUninitialized(BytecodeBufferSize);

	int32 BytecodeIndex = 0;
	while (BytecodeIndex < BytecodeBufferSize)
	{
		DestScriptContainer->SerializeExpr(BytecodeIndex, Ar);
	}
	ensure(ScriptEndOffset == Ar.Tell());
	checkf(BytecodeIndex == BytecodeBufferSize, TEXT("'%s' script expression-count mismatch; Expected: %i, Got: %i"), *DestScriptContainer->GetName(), BytecodeBufferSize, BytecodeIndex);

	if (!GUObjectArray.IsDisregardForGC(DestScriptContainer))
	{
		DestScriptContainer->ScriptObjectReferences.Empty();
		FArchiveScriptReferenceCollector ObjRefCollector(DestScriptContainer->ScriptObjectReferences);

		BytecodeIndex = 0;
		while (BytecodeIndex < BytecodeBufferSize)
		{
			DestScriptContainer->SerializeExpr(BytecodeIndex, ObjRefCollector);
		}
	}

	// success! (we filled the target with serialized script code)
	return true;
}
FPropertyAccess::Result SPropertyEditorAsset::GetValue( FObjectOrAssetData& OutValue ) const
{
	// Potentially accessing the value while garbage collecting or saving the package could trigger a crash.
	// so we fail to get the value when that is occuring.
	if ( GIsSavingPackage || GIsGarbageCollecting )
	{
		return FPropertyAccess::Fail;
	}

	FPropertyAccess::Result Result = FPropertyAccess::Fail;

	if( PropertyEditor.IsValid() && PropertyEditor->GetPropertyHandle()->IsValidHandle() )
	{
		UObject* Object = NULL;
		Result = PropertyEditor->GetPropertyHandle()->GetValue(Object);

		if (Object == NULL)
		{
			// Check to see if it's pointing to an unloaded object
			FString CurrentObjectPath;
			PropertyEditor->GetPropertyHandle()->GetValueAsFormattedString( CurrentObjectPath );

			if (CurrentObjectPath.Len() > 0 && CurrentObjectPath != TEXT("None"))
			{
				if( CurrentObjectPath != TEXT("None") && ( !CachedAssetData.IsValid() || CachedAssetData.ObjectPath.ToString() != CurrentObjectPath ) )
				{
					static FName AssetRegistryName("AssetRegistry");

					FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
					CachedAssetData = AssetRegistryModule.Get().GetAssetByObjectPath( *CurrentObjectPath );
				}

				Result = FPropertyAccess::Success;
				OutValue = FObjectOrAssetData( CachedAssetData );

				return Result;
			}
		}

		OutValue = FObjectOrAssetData( Object );
	}
	else
	{
		const FString CurrentObjectPath = ObjectPath.Get();
		Result = FPropertyAccess::Success;

		if( CurrentObjectPath != TEXT("None") && ( !CachedAssetData.IsValid() || CachedAssetData.ObjectPath.ToString() != CurrentObjectPath ) )
		{
			static FName AssetRegistryName("AssetRegistry");

			FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName);
			CachedAssetData = AssetRegistryModule.Get().GetAssetByObjectPath( *CurrentObjectPath );

			if( PropertyHandle.IsValid() )
			{
				// No property editor was specified so check if multiple property values are associated with the property handle
				TArray<FString> ObjectValues;
				PropertyHandle->GetPerObjectValues( ObjectValues );

				if( ObjectValues.Num() > 1 )
				{
					for( int32 ObjectIndex = 1; ObjectIndex < ObjectValues.Num() && Result == FPropertyAccess::Success; ++ObjectIndex )
					{
						if( ObjectValues[ ObjectIndex ] != ObjectValues[ 0 ] )
						{
							Result = FPropertyAccess::MultipleValues;
						}
					}
				}
			}
		}
		else if( CurrentObjectPath == TEXT("None") )
		{
			CachedAssetData = FAssetData();
		}

		OutValue = FObjectOrAssetData( CachedAssetData );
	}

	return Result;
}
Example #10
0
//----------------------------------------------------------------------------
void NodeCamera::Draw(TArray<NodeCamera*>& rNodeCameras, Spatial* pRoot,
	Culler& rCuller, Renderer* pRenderer)
{
	WIRE_ASSERT(pRenderer && pRoot);
	if (!pRenderer || !pRoot)
	{
		return;
	}

	const UInt maxCameraCount = 64;
	if (rNodeCameras.GetQuantity() >= 64)
	{
		WIRE_ASSERT(false);
		return;
	}

	// cull all skyboxes attached to cameras in the scene
	Spatial::CullingMode tempCullingModes[maxCameraCount];
	for (UInt i = 0; i < rNodeCameras.GetQuantity(); i++)
	{
		NodeCamera* pNodeCamera = rNodeCameras[i];
		WIRE_ASSERT(pNodeCamera);
		Node* pSkybox = pNodeCamera->mspSkybox;
		if (pSkybox && pNodeCamera->IsEnabled())
		{
			tempCullingModes[i] = pSkybox->Culling;
			pSkybox->Culling = Spatial::CULL_ALWAYS;
		}
	}

	for (UInt i = 0; i < rNodeCameras.GetQuantity(); i++)
	{
		NodeCamera* pNodeCamera = rNodeCameras[i];
		WIRE_ASSERT(pNodeCamera && pNodeCamera->Get());
		if (!pNodeCamera->IsEnabled())
		{
			continue;
		}

		Camera* pCamera = pNodeCamera->Get();

		rCuller.SetCamera(pCamera);
		rCuller.ComputeVisibleSet(pRoot);

		Float left;
		Float right;
		Float top;
		Float bottom;
		pCamera->GetViewport(left, right, top, bottom);
		UInt width = pRenderer->GetWidth();
		UInt height = pRenderer->GetHeight();
		Vector4F rect;
		rect.X() = MathF::Round(left*width);
		rect.Y() = MathF::Round((1.0F-top)*height);
		rect.Z() = MathF::Round((right-left)*width);
		rect.W() = MathF::Round((top-bottom)*height);

		ColorRGBA clearColor = pRenderer->GetClearColor();
		switch (rNodeCameras[i]->mClearFlag)
		{
		case CF_ALL:
			pRenderer->SetClearColor(pNodeCamera->GetClearColor());
			pRenderer->ClearBuffers(true, true, rect);
			pRenderer->SetClearColor(clearColor);
			break;

		case CF_Z_ONLY:
			pRenderer->ClearBuffers(false, true, rect);
			break;

		case CF_NONE:		
			break;

		default:
			WIRE_ASSERT(false);
		}

		pRenderer->SetCamera(pCamera);
		pRenderer->Draw(rCuller.GetVisibleSets());

		Node* pSkybox = pNodeCamera->mspSkybox;
		if (pSkybox)
		{
			pSkybox->Culling = Spatial::CULL_NEVER;
			rCuller.ComputeVisibleSet(pSkybox);
			pRenderer->Draw(rCuller.GetVisibleSets());
			pSkybox->Culling = Spatial::CULL_ALWAYS;
		}
	}

	// restore culling mode of all skyboxes attached to cameras in the scene
	for (UInt i = 0; i < rNodeCameras.GetQuantity(); i++)
	{
		NodeCamera* pNodeCamera = rNodeCameras[i];
		WIRE_ASSERT(pNodeCamera);
		Node* pSkybox = pNodeCamera->mspSkybox;
		if (pSkybox && pNodeCamera->IsEnabled())
		{
			pSkybox->Culling = tempCullingModes[i];
		}
	}
}
int32 GenerateKDopAsSimpleCollision(UStaticMesh* StaticMesh, const TArray<FVector> &Dirs)
{
	// Make sure rendering is done - so we are not changing data being used by collision drawing.
	FlushRenderingCommands();

	if (!PromptToRemoveExistingCollision(StaticMesh))
	{
		return INDEX_NONE;
	}

	UBodySetup* bs = StaticMesh->BodySetup;

	// Do k- specific stuff.
	int32 kCount = Dirs.Num();
	TArray<float> maxDist;
	for(int32 i=0; i<kCount; i++)
		maxDist.Add(-MY_FLTMAX);

	// Construct temporary UModel for kdop creation. We keep no refs to it, so it can be GC'd.
	auto TempModel = NewObject<UModel>();
	TempModel->Initialize(nullptr, 1);

	// For each vertex, project along each kdop direction, to find the max in that direction.
	const FStaticMeshLODResources& RenderData = StaticMesh->RenderData->LODResources[0];
	for(int32 i=0; i<RenderData.GetNumVertices(); i++)
	{
		for(int32 j=0; j<kCount; j++)
		{
			float dist = RenderData.PositionVertexBuffer.VertexPosition(i) | Dirs[j];
			maxDist[j] = FMath::Max(dist, maxDist[j]);
		}
	}

	// Inflate kdop to ensure it is no degenerate
	const float MinSize = 0.1f;
	for(int32 i=0; i<kCount; i++)
	{
		maxDist[i] += MinSize;
	}

	// Now we have the planes of the kdop, we work out the face polygons.
	TArray<FPlane> planes;
	for(int32 i=0; i<kCount; i++)
		planes.Add( FPlane(Dirs[i], maxDist[i]) );

	for(int32 i=0; i<planes.Num(); i++)
	{
		FPoly*	Polygon = new(TempModel->Polys->Element) FPoly();
		FVector Base, AxisX, AxisY;

		Polygon->Init();
		Polygon->Normal = planes[i];
		Polygon->Normal.FindBestAxisVectors(AxisX,AxisY);

		Base = planes[i] * planes[i].W;

		new(Polygon->Vertices) FVector(Base + AxisX * HALF_WORLD_MAX + AxisY * HALF_WORLD_MAX);
		new(Polygon->Vertices) FVector(Base + AxisX * HALF_WORLD_MAX - AxisY * HALF_WORLD_MAX);
		new(Polygon->Vertices) FVector(Base - AxisX * HALF_WORLD_MAX - AxisY * HALF_WORLD_MAX);
		new(Polygon->Vertices) FVector(Base - AxisX * HALF_WORLD_MAX + AxisY * HALF_WORLD_MAX);

		for(int32 j=0; j<planes.Num(); j++)
		{
			if(i != j)
			{
				if(!Polygon->Split(-FVector(planes[j]), planes[j] * planes[j].W))
				{
					Polygon->Vertices.Empty();
					break;
				}
			}
		}

		if(Polygon->Vertices.Num() < 3)
		{
			// If poly resulted in no verts, remove from array
			TempModel->Polys->Element.RemoveAt(TempModel->Polys->Element.Num()-1);
		}
		else
		{
			// Other stuff...
			Polygon->iLink = i;
			Polygon->CalcNormal(1);
		}
	}

	if(TempModel->Polys->Element.Num() < 4)
	{
		TempModel = NULL;
		return INDEX_NONE;
	}

	// Build bounding box.
	TempModel->BuildBound();

	// Build BSP for the brush.
	FBSPOps::bspBuild(TempModel,FBSPOps::BSP_Good,15,70,1,0);
	FBSPOps::bspRefresh(TempModel,1);
	FBSPOps::bspBuildBounds(TempModel);

	bs->Modify();

	bs->CreateFromModel(TempModel, false);
	
	// create all body instances
	RefreshCollisionChange(StaticMesh);

	// Mark staticmesh as dirty, to help make sure it gets saved.
	StaticMesh->MarkPackageDirty();

	return bs->AggGeom.ConvexElems.Num() - 1;
}
UObject* USspjFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* InBufferEnd, FFeedbackContext* Warn)
{
	bool bReimport = this->IsA(UReimportSspjFactory::StaticClass());
	TMap<FString, UTexture*>* ExistImages = NULL;
	if(bReimport)
	{
		ExistImages = &(Cast<UReimportSspjFactory>(this)->ExistImages);
	}

	FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");

	FString ProjectNameStr = InName.ToString();
	FName ProjectName = InName;

	UPackage* InParentPackage = Cast<UPackage>(InParent);
	if(InParentPackage && !bReimport)
	{
		FString ProjectPackageName;
		FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / ProjectNameStr;
		AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), ProjectPackageName, ProjectNameStr);
		InParentPackage->Rename(*ProjectPackageName);
	}

	// インポート設定の取得 
	const USsImportSettings* ImportSettings = GetDefault<USsImportSettings>();

	// インポート開始 
	FEditorDelegates::OnAssetPreImport.Broadcast(this, InClass, InParent, ProjectName, Type);

	// sspj
	USsProject* NewProject = FSsLoader::LoadSsProject(InParent, ProjectName, Flags, Buffer, (InBufferEnd - Buffer) + 1);
	NewProject->SetFilepath( GetCurrentFilename() );
	if(NewProject)
	{
		if(NewProject->AssetImportData == nullptr)
		{
			NewProject->AssetImportData = NewObject<UAssetImportData>(NewProject);
		}
		NewProject->AssetImportData->Update(CurrentFilename);

		FString CurPath = FPaths::GetPath(GetCurrentFilename());

		TArray<FString> ImagePaths;
		TArray<SsTexWrapMode::Type> ImageWrapModes;
		TArray<SsTexFilterMode::Type> ImageFilterModes;

		// ssce
		NewProject->CellmapList.Empty();
		NewProject->CellmapList.AddZeroed(NewProject->CellmapNames.Num());
		for(int i = 0; i < NewProject->CellmapNames.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.CellMapBaseDirectory, NewProject->CellmapNames[i].ToString());

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{
				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num() - 1;
				if(FSsLoader::LoadSsCellMap(&(NewProject->CellmapList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1))
				{
					NewProject->CellmapList[i].FileName = NewProject->CellmapNames[i];
					if(0 < NewProject->CellmapList[i].ImagePath.Len())
					{
						if(INDEX_NONE == ImagePaths.Find(NewProject->CellmapList[i].ImagePath))
						{
							ImagePaths.Add(NewProject->CellmapList[i].ImagePath);
							if(NewProject->CellmapList[i].OverrideTexSettings)
							{
								ImageWrapModes.Add(NewProject->CellmapList[i].WrapMode);
								ImageFilterModes.Add(NewProject->CellmapList[i].FilterMode);
							}
							else
							{
								ImageWrapModes.Add(NewProject->Settings.WrapMode);
								ImageFilterModes.Add(NewProject->Settings.FilterMode);
							}
						}
					}
				}
			}
		}

		// ssae
		NewProject->AnimeList.Empty();
		NewProject->AnimeList.AddZeroed(NewProject->AnimepackNames.Num());
		for(int i = 0; i < NewProject->AnimepackNames.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.AnimeBaseDirectory, NewProject->AnimepackNames[i].ToString());

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{
				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num() - 1;
				FSsLoader::LoadSsAnimePack(&(NewProject->AnimeList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1);
			}
		}

		// texture
		for(int i = 0; i < ImagePaths.Num(); ++i)
		{
			FString FileName = GetFilePath(CurPath, NewProject->Settings.ImageBaseDirectory, ImagePaths[i]);

			UTexture* ImportedTexture = NULL;
			if(ExistImages && ExistImages->Contains(ImagePaths[i]))
			{
				ImportedTexture = ExistImages->FindChecked(ImagePaths[i]);
			}

			TArray<uint8> Data;
			if(FFileHelper::LoadFileToArray(Data, *FileName))
			{

				UTextureFactory* TextureFact = NewObject<UTextureFactory>();
				TextureFact->AddToRoot();

				FString TextureName = FPaths::GetBaseFilename(ImagePaths[i]);

				UPackage* TexturePackage = NULL;
				if(ImportedTexture)
				{
					TexturePackage = ImportedTexture->GetOutermost();
				}
				else
				{
					FString TexturePackageName;
					FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / TextureName;
					AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), TexturePackageName, TextureName);
					TexturePackage = CreatePackage(NULL, *TexturePackageName);
				}

				const uint8* BufferBegin = Data.GetData();
				const uint8* BufferEnd = BufferBegin + Data.Num();
				UTexture2D* NewTexture = (UTexture2D*)TextureFact->FactoryCreateBinary(
					UTexture2D::StaticClass(),
					TexturePackage,
					FName(*TextureName),
					Flags,
					NULL,
					*FPaths::GetExtension(ImagePaths[i]),
					BufferBegin, BufferEnd,
					Warn
					);
				if(NewTexture)
				{
					if(ImportSettings->bOverwriteMipGenSettings)
					{
						NewTexture->MipGenSettings = TMGS_NoMipmaps;
					}
					if(ImportSettings->bOverwriteTextureGroup)
					{
						NewTexture->LODGroup = ImportSettings->TextureGroup;
					}
					if(ImportSettings->bOverwriteCompressionSettings)
					{
						NewTexture->CompressionSettings = TextureCompressionSettings::TC_EditorIcon;
					}
					if(ImportSettings->bOverwriteTilingMethodFromSspj)
					{
						switch(ImageWrapModes[i])
						{
							case SsTexWrapMode::Clamp:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Clamp;
								} break;
							case SsTexWrapMode::Repeat:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Wrap;
								} break;
							case SsTexWrapMode::Mirror:
								{
									NewTexture->AddressX = NewTexture->AddressY = TA_Mirror;
								} break;
						}
					}
					if(ImportSettings->bOverwriteNeverStream)
					{
						NewTexture->NeverStream = true;
					}
					if(ImportSettings->bOverwriteFilterFromSspj)
					{
						switch(ImageFilterModes[i])
						{
							case SsTexFilterMode::Nearest:
								{
									NewTexture->Filter = TF_Nearest;
								} break;
							case SsTexFilterMode::Linear:
								{
									NewTexture->Filter = TF_Bilinear;
								} break;
						}
					}

					NewTexture->UpdateResource();

					FAssetRegistryModule::AssetCreated(NewTexture);
					TexturePackage->SetDirtyFlag(true);

					TextureFact->RemoveFromRoot();

					ImportedTexture = NewTexture;
				}
			}

			if(ImportedTexture)
			{
				for(int ii = 0; ii < NewProject->CellmapList.Num(); ++ii)
				{
					if(NewProject->CellmapList[ii].ImagePath == ImagePaths[i])
					{
						NewProject->CellmapList[ii].Texture = ImportedTexture;
					}
				}
			}
		}
	}

	// インポート終了
	FEditorDelegates::OnAssetPostImport.Broadcast(this, NewProject);
	return NewProject;
}
Example #13
0
void FEdModeGeometry::RenderPoly( const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI )
{
	for( int32 ObjectIdx = 0 ; ObjectIdx < GeomObjects.Num() ; ++ObjectIdx )
	{
		const FGeomObject* GeomObject = GeomObjects[ObjectIdx];
		
		FLinearColor UnselectedColor = GeomObject->GetActualBrush()->GetWireColor();
		UnselectedColor.A = .1f;

		FLinearColor SelectedColor = GetDefault<UEditorStyleSettings>()->SelectionColor;
		SelectedColor.A = .5f;

		// Allocate the material proxy and register it so it can be deleted properly once the rendering is done with it.
		FDynamicColoredMaterialRenderProxy* SelectedColorInstance = new FDynamicColoredMaterialRenderProxy(GEngine->GeomMaterial->GetRenderProxy(false),SelectedColor );
		PDI->RegisterDynamicResource( SelectedColorInstance );

		FDynamicColoredMaterialRenderProxy* UnselectedColorInstance = new FDynamicColoredMaterialRenderProxy(GEngine->GeomMaterial->GetRenderProxy(false),UnselectedColor);
		PDI->RegisterDynamicResource( UnselectedColorInstance );		

		// Render selected filled polygons.
		for( int32 PolyIdx = 0 ; PolyIdx < GeomObject->PolyPool.Num() ; ++PolyIdx )
		{
			const FGeomPoly* GeomPoly = &GeomObject->PolyPool[PolyIdx];
			PDI->SetHitProxy( new HGeomPolyProxy(const_cast<FGeomObject*>(GeomPoly->GetParentObject()),PolyIdx) );
			{
				FDynamicMeshBuilder MeshBuilder;

				TArray<FVector> Verts;

				// Look at the edge list and create a list of vertices to render from.

				FVector LastPos(0);

				for( int32 EdgeIdx = 0 ; EdgeIdx < GeomPoly->EdgeIndices.Num() ; ++EdgeIdx )
				{
					const FGeomEdge* GeomEdge = &GeomPoly->GetParentObject()->EdgePool[ GeomPoly->EdgeIndices[EdgeIdx] ];

					if( EdgeIdx == 0 )
					{
						Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ] );
						LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ];
					}
					else if( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ].Equals( LastPos ) )
					{
						Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[1] ] );
						LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[1] ];
					}
					else
					{
						Verts.Add( GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ] );
						LastPos = GeomPoly->GetParentObject()->VertexPool[ GeomEdge->VertexIndices[0] ];
					}
				}

				// Draw Polygon Triangles
				const int32 VertexOffset = MeshBuilder.AddVertex(Verts[0], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor::White);
				MeshBuilder.AddVertex(Verts[1], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor::White);

				for( int32 VertIdx = 2 ; VertIdx < Verts.Num() ; ++VertIdx )
				{
					MeshBuilder.AddVertex(Verts[VertIdx], FVector2D::ZeroVector, FVector(1,0,0), FVector(0,1,0), FVector(0,0,1), FColor::White);
					MeshBuilder.AddTriangle( VertexOffset + VertIdx - 1, VertexOffset, VertexOffset + VertIdx);
				}

				if( GeomPoly->IsSelected() )
				{
					MeshBuilder.Draw(PDI, GeomObject->GetActualBrush()->ActorToWorld().ToMatrixWithScale(), SelectedColorInstance, SDPG_World, false );
				}
				else
				{
					// We only draw unselected polygons in the perspective viewport
					if( !Viewport->GetClient()->IsOrtho() )
					{
						// Unselected polygons are drawn at the world level but are bumped slightly forward to avoid z-fighting
						MeshBuilder.Draw(PDI, GeomObject->GetActualBrush()->ActorToWorld().ToMatrixWithScale(), UnselectedColorInstance, SDPG_World, false );
					}
				}
			}
			PDI->SetHitProxy( NULL );
		}
	}
}
Example #14
0
/**
 * Attempt to find all the new geometry using the cached data, and cache those new ones out
 *
 * Return true everything was found (or there was nothing to find)
 */
bool FEdModeGeometry::FindFromCache( TArray<HGeomMidPoints>& raGeomData, FGeomObject& rGeomObject, TArray<FGeomBase*>& raSelectedGeom ) const
{
	// Early out if this object doesn't have a brush
	if ( !rGeomObject.ActualBrush )
	{
		return true;
	}

	// Early out if we don't have anything cached
	if ( raGeomData.Num() == 0 )
	{
		return true;
	}

	// Loop through all the cached data, seeing if there's a match for the brush
	// Note: if GetMidPoint wasn't pure virtual this could be much nicer
	bool bRet = false;		// True if the brush that was parsed was found and all verts/edges/polys were located
	bool bFound = false;	// True if the brush that was parsed was found
	for( int32 i=0; i<raGeomData.Num(); i++ )
	{
		// Does this brush match the cached actor?
		HGeomMidPoints& rGeomData = raGeomData[i];
		if ( rGeomData.ActualBrush == rGeomObject.ActualBrush )
		{
			// Compare location of new midpoints with cached versions
			bFound = true;
			bool bSucess = true;		// True if all verts/edges/polys were located
			for ( int32 j=0; j<rGeomData.VertexPool.Num(); j++ )
			{
				const FVector& rGeomVector = rGeomData.VertexPool[j];
				for ( int32 k=0; k<rGeomObject.VertexPool.Num(); k++ )
				{
					// If we have a match select it and move on to the next one
					FGeomVertex& rGeomVertex = rGeomObject.VertexPool[k];
					if ( rGeomVector.Equals( rGeomVertex.GetMidPoint() ) )
					{
						// Add the new geometry to the to-be-selected pool, and remove from the data pool
						raSelectedGeom.Add(&rGeomVertex);
						rGeomData.VertexPool.RemoveAt(j--);
						break;
					}
				}
			}
			// If we didn't locate them all inform the user
			if ( rGeomData.VertexPool.Num() != 0 )
			{
				UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find %d Vertex(s) in new BSP" ), rGeomData.VertexPool.Num() );
				bSucess = false;
			}

			// Compare location of new midpoints with cached versions
			for ( int32 j=0; j<rGeomData.EdgePool.Num(); j++ )
			{
				const FVector& rGeomVector = rGeomData.EdgePool[j];
				for ( int32 k=0; k<rGeomObject.EdgePool.Num(); k++ )
				{
					// If we have a match select it and move on to the next one
					FGeomEdge& rGeomEdge = rGeomObject.EdgePool[k];
					if ( rGeomVector.Equals( rGeomEdge.GetMidPoint() ) )
					{
						// Add the new geometry to the to-be-selected pool, and remove from the data pool
						raSelectedGeom.Add(&rGeomEdge);
						rGeomData.EdgePool.RemoveAt(j--);
						break;
					}
				}
			}
			// If we didn't locate them all inform the user
			if ( rGeomData.EdgePool.Num() != 0 )
			{
				UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find %d Edge(s) in new BSP" ), rGeomData.EdgePool.Num() );
				bSucess = false;
			}

			// Compare location of new midpoints with cached versions
			for ( int32 j=0; j<rGeomData.PolyPool.Num(); j++ )
			{
				const FVector& rGeomVector = rGeomData.PolyPool[j];
				for ( int32 k=0; k<rGeomObject.PolyPool.Num(); k++ )
				{
					// If we have a match select it and move on to the next one
					FGeomPoly& rGeomPoly = rGeomObject.PolyPool[k];
					if ( rGeomVector.Equals( rGeomPoly.GetMidPoint() ) )
					{
						// Add the new geometry to the to-be-selected pool, and remove from the data pool
						raSelectedGeom.Add(&rGeomPoly);
						rGeomData.PolyPool.RemoveAt(j--);
						break;
					}
				}
			}
			// If we didn't locate them all inform the user
			if ( rGeomData.PolyPool.Num() != 0 )
			{
				UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find %d Poly(s) in new BSP" ), rGeomData.PolyPool.Num() );
				bSucess = false;
			}

			// If we didn't locate them all inform the user, then remove from the data pool
			if ( !bSucess )
			{
				UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to resolve %s Brush in new BSP, see above" ), *rGeomData.ActualBrush->GetName() );
			}
			bRet = bSucess;
			raGeomData.RemoveAt(i--);
			break;
		}
	}
	// If we didn't locate the brush inform the user
	if ( !bFound )
	{
		UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find %s Brush(s) in new BSP" ), *rGeomObject.ActualBrush->GetName() );
	}
	return bRet;
}
bool FSubversionConnectWorker::Execute(FSubversionSourceControlCommand& InCommand)
{
	check(InCommand.Operation->GetName() == GetName());
	TSharedRef<FConnect, ESPMode::ThreadSafe> Operation = StaticCastSharedRef<FConnect>(InCommand.Operation);
	FString Password = InCommand.Password;
	// see if we are getting a password passed in from the calling code
	if(Operation->GetPassword().Len() > 0)
	{
		Password = Operation->GetPassword();
	}

	{
		TArray<FXmlFile> ResultsXml;
		TArray<FString> Parameters;
		FString GameRoot = FPaths::ConvertRelativePathToFull(FPaths::GameDir());
		// We need to manually quote the filename because we're not passing the file argument via RunCommand's InFiles parameter
		SubversionSourceControlUtils::QuoteFilename(GameRoot);
		Parameters.Add(GameRoot);
	
		InCommand.bCommandSuccessful = SubversionSourceControlUtils::RunCommand(TEXT("info"), TArray<FString>(), Parameters, ResultsXml, InCommand.ErrorMessages, InCommand.UserName, Password);	
		if(InCommand.bCommandSuccessful)
		{
			SubversionSourceControlUtils::ParseInfoResults(ResultsXml, WorkingCopyRoot, RepositoryRoot);
		}
	}

	if(InCommand.bCommandSuccessful)
	{
		TArray<FXmlFile> ResultsXml;
		TArray<FString> Files;
		FString GameRoot = FPaths::ConvertRelativePathToFull(FPaths::GameDir());
		Files.Add(GameRoot);

		TArray<FString> StatusParameters;
		StatusParameters.Add(TEXT("--show-updates"));
		StatusParameters.Add(TEXT("--verbose"));

		InCommand.bCommandSuccessful = SubversionSourceControlUtils::RunCommand(TEXT("status"), Files, StatusParameters, ResultsXml, InCommand.ErrorMessages, InCommand.UserName, Password);

		if(InCommand.bCommandSuccessful)
		{
			// Check to see if this was a working copy - if not deny connection as we wont be able to work with it.
			TArray<FSubversionSourceControlState> States;
			SubversionSourceControlUtils::ParseStatusResults(ResultsXml, InCommand.ErrorMessages, InCommand.UserName, InCommand.WorkingCopyRoot, States);
			if(InCommand.ErrorMessages.Num() > 0)
			{
				for (int32 MessageIndex = 0; MessageIndex < InCommand.ErrorMessages.Num(); ++MessageIndex)
				{
					const FString& Error = InCommand.ErrorMessages[MessageIndex];
					int32 Pattern = Error.Find(TEXT("' is not a working copy"), ESearchCase::IgnoreCase, ESearchDir::FromStart);
					if(Pattern != INDEX_NONE)
					{
						StaticCastSharedRef<FConnect>(InCommand.Operation)->SetErrorText(LOCTEXT("NotAWorkingCopyError", "Project is not part of an SVN working copy."));
						InCommand.ErrorMessages.Add(LOCTEXT("NotAWorkingCopyErrorHelp", "You should check out a working copy into your project directory.").ToString());
						InCommand.bCommandSuccessful = false;
						break;
					}
				}
			}
		}	
	}

	return InCommand.bCommandSuccessful;
}
//Rama's String From Binary Array
//This function requires #include <string>
FString CloudyWebConnectorImpl::StringFromBinaryArray(const TArray<uint8>& BinaryArray)
{
    //Create a string from a byte array!
    std::string cstr(reinterpret_cast<const char*>(BinaryArray.GetData()), BinaryArray.Num());
    return FString(cstr.c_str());
}
void FNiagaraSimulation::RunVMScript(FNiagaraEmitterScriptProperties& ScriptProps, EUnusedAttributeBehaviour UnusedAttribBehaviour, uint32 StartParticle, uint32 NumParticles)
{
	if (NumParticles == 0)
	{
		return;
	}
	
	UNiagaraScript* Script = ScriptProps.Script;

	check(Script);
	check(Script->ByteCode.Num() > 0);
	check(Script->Attributes.Num() > 0);
	check(Data.GetNumVariables() > 0);

	uint32 CurrNumParticles = Data.GetNumInstances();

	check(StartParticle + NumParticles <= CurrNumParticles);

	VectorRegister* InputRegisters[VectorVM::MaxInputRegisters] = { 0 };
	VectorRegister* OutputRegisters[VectorVM::MaxOutputRegisters] = { 0 };
	
	//The current script run will be using NumScriptAttrs. We must pick out the Attributes form the simulation data in the order that they appear in the script.
	//The remaining attributes being handled according to UnusedAttribBehaviour
	const int32 NumScriptAttrs = Script->Attributes.Num();

	check(NumScriptAttrs < VectorVM::MaxInputRegisters);
	check(NumScriptAttrs < VectorVM::MaxOutputRegisters);

	int32 NumInputRegisters = 0;
	int32 NumOutputRegitsers = 0;

	{
		SCOPE_CYCLE_COUNTER(STAT_NiagaraSimRegisterSetup);

		// Setup input and output registers.
		for (TPair<FNiagaraVariableInfo, uint32> AttrIndexPair : Data.GetVariables())
		{
			const FNiagaraVariableInfo& AttrInfo = AttrIndexPair.Key;

			FVector4* InBuff;
			FVector4* OutBuff;
			Data.GetVariableData(AttrInfo, InBuff, OutBuff, StartParticle);

			int32 AttrIndex = Script->Attributes.Find(AttrInfo);
			if (AttrIndex != INDEX_NONE)
			{
				//The input buffer can be NULL but only if this script never accesses it.
				check(InBuff || !Script->Usage.bReadsAttriubteData);

				//This attribute is used in this script so set it to the correct Input and Output buffer locations.
				InputRegisters[AttrIndex] = (VectorRegister*)InBuff;
				OutputRegisters[AttrIndex] = (VectorRegister*)OutBuff;

				NumInputRegisters += InBuff ? 1 : 0;
				NumOutputRegitsers += OutBuff ? 1 : 0;
			}
			else
			{
				//This attribute is not used in this script so handle it accordingly.
				check(OutBuff);

				if (UnusedAttribBehaviour == EUnusedAttributeBehaviour::PassThrough)
				{
					Data.GetVariableBuffer(AttrInfo).EnablePassThrough();
				}
				else if (UnusedAttribBehaviour == EUnusedAttributeBehaviour::Copy)
				{
					check(InBuff);
					FMemory::Memcpy(OutBuff, InBuff, NumParticles * sizeof(FVector4));
				}
				else if (UnusedAttribBehaviour == EUnusedAttributeBehaviour::Zero)
				{
					FMemory::Memzero(OutBuff, NumParticles * sizeof(FVector4));
				}
				else if (UnusedAttribBehaviour == EUnusedAttributeBehaviour::MarkInvalid)
				{
					FMemory::Memset(OutBuff, NIAGARA_INVALID_MEMORY, NumParticles * sizeof(FVector4));
				}
			}
		}
	}

	// Fill constant table with required emitter constants and internal script constants.
	TArray<FVector4> ConstantTable;
	//Script->ConstantData.FillConstantTable(ExternalConstantsMap, ConstantTable);
	Script->ConstantData.FillConstantTable(ExternalConstants, ConstantTable);


	// Fill in the shared data table
	TArray<FVectorVMSharedDataView, TInlineAllocator<64>> SharedDataTable;
	
	for (FNiagaraEventReceiverProperties Receiver : ScriptProps.EventReceivers)
	{
		//Look up to the effect for receiver sets as they can come from other emitters.
		FNiagaraDataSetID ReceiverID = FNiagaraDataSetID(Receiver.Name, ENiagaraDataSetType::Event);
		FNiagaraDataSetID SourceID = FNiagaraDataSetID(Receiver.SourceEventGenerator, ENiagaraDataSetType::Event);
		
		FNiagaraDataSet* SourceSet = ParentEffectInstance->GetDataSet(SourceID, Receiver.SourceEmitter);
		FNiagaraDataSetProperties* ScriptEventReceiver = Script->EventReceivers.FindByPredicate([&](const FNiagaraDataSetProperties& R){ return ReceiverID == R.ID; });

		check(ScriptEventReceiver);

		uint32 NumInstances = SourceSet ? SourceSet->GetPrevNumInstances() : 0;
		int32 ViewIdx = SharedDataTable.Add(FVectorVMSharedDataView(NumInstances, NumInstances - 1));
		FVectorVMSharedDataView& View = SharedDataTable[ViewIdx];
		for (FNiagaraVariableInfo& Var : ScriptEventReceiver->Variables)
		{
			FVector4* ReadData = SourceSet ? SourceSet->GetPrevVariableData(Var) : nullptr;
			View.AddBuffer(ReadData);			
		}
	}

	//Keep track of all the generator sets so that we can set their instance numbers after the VM run.
	int32 StartOfGeneratorSets = SharedDataTable.Num();
	TArray<FNiagaraDataSet*, TInlineAllocator<64>> GeneratorSets;

	//TODO: Allow growing arrays for shared data / events in VM? HMMMM
	for (FNiagaraEventGeneratorProperties Generator : ScriptProps.EventGenerators)
	{
		FNiagaraDataSet* GeneratorSet = DataSetMap.FindChecked(Generator.ID);
		GeneratorSets.Add(GeneratorSet);
	
		check(GeneratorSet);

		uint32 Allocation = GeneratorSet->GetDataAllocation();
		uint32 NumInstances = GeneratorSet->GetNumInstances();

		int32 ViewIdx = SharedDataTable.Add(FVectorVMSharedDataView(Allocation, NumInstances));
		FVectorVMSharedDataView& View = SharedDataTable[ViewIdx];

		for (FNiagaraVariableInfo& Var : Generator.Variables)
		{
			FVector4* WriteData = GeneratorSet->GetVariableData(Var);
			View.AddBuffer(WriteData);
		}
	}
	
	VectorVM::Exec(
		Script->ByteCode.GetData(),
		InputRegisters,
		NumInputRegisters,
		OutputRegisters,
		NumOutputRegitsers,
		ConstantTable.GetData(),
		SharedDataTable.Num() > 0 ? SharedDataTable.GetData() : NULL,
		NumParticles
		);

	//Go through our generators and set the num instances that were actually written ready for them to be read by receivers.
	for (int32 i = 0; i < GeneratorSets.Num(); ++i)
	{
		FVectorVMSharedDataView& View = SharedDataTable[StartOfGeneratorSets + i];
		FNiagaraDataSet* GeneratorSet = GeneratorSets[i];
		check(GeneratorSet);
		GeneratorSet->SetNumInstances(View.GetCounter());
		INC_DWORD_STAT_BY(STAT_NiagaraNumCustomEvents, View.GetCounter());
	}
}
Example #18
0
bool CCSVParser::ParseRow (TArray<CString> &Row, CString *retsError)

//	ParseRow
//
//	Parses a row

	{
	enum EStates
		{
		stateStart,
		stateSingleQuote,
		stateDoubleQuote,
		stateInPlainValue,
		stateEndOfValue,
		stateCR,
		stateLF,
		};

	Row.DeleteAll();

	//	Parse the BOM, if any

	if (m_iFormat == formatUnknown)
		m_iFormat = ParseBOM();

	//	Keep reading until we hit the end of the line.

	EStates iState = stateStart;
	CBuffer Value;
	while (true)
		{
		switch (iState)
			{
			case stateStart:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case ' ':
					case '\t':
						break;

					case ',':
						Row.Insert(NULL_STR);
						break;

					case '\r':
						iState = stateCR;
						break;

					case '\n':
						iState = stateLF;
						break;

					case '\'':
						iState = stateSingleQuote;
						break;

					case '\"':
						iState = stateDoubleQuote;
						break;

					default:
						Value.WriteChar(GetCurChar());
						iState = stateInPlainValue;
						break;
					}
				break;
				}

			case stateSingleQuote:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case '\'':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateEndOfValue;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateDoubleQuote:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case '\"':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateEndOfValue;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateEndOfValue:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case ' ':
					case '\t':
						break;

					case ',':
						iState = stateStart;
						break;

					case '\r':
						iState = stateCR;
						break;

					case '\n':
						iState = stateLF;
						break;

					default:
						break;
					}
				break;
				}

			case stateInPlainValue:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case ',':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateStart;
						break;

					case '\r':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateCR;
						break;

					case '\n':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateLF;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateCR:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case '\n':
						GetNextChar();
						return true;

					default:
						break;
					}
				break;
				}

			case stateLF:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case '\r':
						GetNextChar();
						return true;

					default:
						return true;
					}
				break;
				}
			}

		GetNextChar();
		}
	}
void SDeviceProfileDetailsPanel::RefreshUI()
{
	DetailsViewBox->ClearChildren();

	// initialize settings view
	FDetailsViewArgs DetailsViewArgs;
	{
		DetailsViewArgs.bAllowSearch = true;
		DetailsViewArgs.bHideSelectionTip = true;
		DetailsViewArgs.bLockable = false;
		DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
		DetailsViewArgs.bSearchInitialKeyFocus = true;
		DetailsViewArgs.bUpdatesFromSelection = false;
		DetailsViewArgs.bShowOptions = false;
	}

	SettingsView = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor").CreateDetailView(DetailsViewArgs);

	if( ViewingProfile.IsValid() )
	{
		const FSlateBrush* DeviceProfileTypeIcon = FEditorStyle::GetDefaultBrush();
		TArray<ITargetPlatform*> TargetPlatforms = GetTargetPlatformManager()->GetTargetPlatforms();
		if (TargetPlatforms.Num())
		{
			DeviceProfileTypeIcon = FEditorStyle::GetBrush(TargetPlatforms[0]->GetPlatformInfo().GetIconStyleName(PlatformInfo::EPlatformIconSize::Normal));
		}

		SettingsView->SetObject(&*ViewingProfile);
		// If a profile is provided, show the details for this profile.
		DetailsViewBox->AddSlot()
		[
			SNew( SBorder )
			.BorderImage( FEditorStyle::GetBrush( "ToolBar.Background" ) )
			[
				SNew( SVerticalBox )
				+ SVerticalBox::Slot()
				.HAlign( HAlign_Left )
				.AutoHeight()
				[
					SNew( SHorizontalBox )
					+ SHorizontalBox::Slot()
					.AutoWidth()
					.Padding(4.0f, 0.0f, 2.0f, 0.0f)
					[
						SNew(SImage)
						.Image(DeviceProfileTypeIcon)
					]

					+SHorizontalBox::Slot()
					[
						SNew(SVerticalBox)
						+SVerticalBox::Slot()
						.VAlign(VAlign_Center)
						[
							SNew( STextBlock )
							.Text( FText::Format( LOCTEXT( "SelectedDeviceProfileFmt", "{0} selected" ), FText::FromString(ViewingProfile->GetName()) ) )
						]
					]
				]

				/**
				 * CVars part of the details panel
				 */
				+ SVerticalBox::Slot()
				.Padding(4.0f)
				.FillHeight(1.0f)
				[
					SNew(SScrollBox)
					+ SScrollBox::Slot()
					[
						SNew( SBorder )
						.BorderImage( FEditorStyle::GetBrush( "Docking.Tab.ContentAreaBrush" ) )
						[
							SNew( SVerticalBox )
							+ SVerticalBox::Slot()
							.FillHeight(1.0f)
							.Padding( FMargin( 4.0f ) )
							[
								SettingsView.ToSharedRef()
							]
						]
					]
				]
			]
		];
	}
	else
	{
		// No profile was selected, so the panel should reflect this
		DetailsViewBox->AddSlot()
			[
				SNew( SBorder )
				.BorderImage( FEditorStyle::GetBrush( "ToolBar.Background" ) )
				[
					SNew(SVerticalBox)
					+SVerticalBox::Slot()
					.VAlign( VAlign_Top )
					.HAlign( HAlign_Center )
					.Padding( 4.0f )
					[
						SNew( STextBlock )
						.Text( LOCTEXT("SelectAProfile", "Select a device profile above...") )					
					]

				]
			];
	}
}
void CGlxCollectionPluginAlbums::HandleCpiAttributeResponseL(CMPXMedia* aResponse, TArray<TMPXAttribute> aCpiAttributes, TGlxMediaId aMediaId)
    {
    _LIT(KResourceFile, "z:glxpluginalbums.rsc");

    const TInt attribCount = aCpiAttributes.Count();

    for (TInt index = 0; index < attribCount ; index++)
        {
        const TMPXAttribute attr = aCpiAttributes[index];
        
        if (attr == KGlxMediaCollectionPluginSpecificSubTitle)
            {
            TInt usageCount = 0;
            if ( aResponse->IsSupported(KMPXMediaGeneralCount) )
                {
                usageCount = aResponse->ValueTObjectL<TInt>(KMPXMediaGeneralCount);
                }
            else if ( aResponse->IsSupported(KGlxMediaCollectionInternalUsageCount) )
                {
                usageCount = aResponse->ValueTObjectL<TInt>(KGlxMediaCollectionInternalUsageCount);
                aResponse->Delete(KGlxMediaCollectionInternalUsageCount);
                }
            else
                {
                User::Leave(KErrNotSupported);
                }
            HBufC* tempTitle = NULL;
            
            if (TGlxMediaId(KGlxCollectionRootId) == aMediaId)
            	{
                if (1 == usageCount)
                	{
                    tempTitle = LoadLocalizedStringLC(KResourceFile, R_ALBUM_SUB_TITLE_SINGLE);
                	}
                else
                	{
                	tempTitle = LoadLocalizedStringLC(KResourceFile, R_ALBUM_SUB_TITLE_MULTI);
                	}
            	}
            else
            	{
                tempTitle = HbTextResolverSymbian::LoadLC(KAlbumContainer, usageCount);
         
                	
                	// Set the title in the response.
            		aResponse->SetTextValueL(attr, *tempTitle);  
            		CleanupStack::PopAndDestroy(tempTitle);
            		continue;                	
            	}
            
            TPtr formatString = tempTitle->Des();
            
            // Now create a buffer that will contain the result. needs to be length of format string plus a few extra for the number
            HBufC* title = HBufC::NewLC(formatString.Length() + 10);
            TPtr ptr = title->Des();
            StringLoader::Format(ptr, formatString, -1, usageCount);
            
            // Set the title in the response.
            aResponse->SetTextValueL(attr, *title);    

            CleanupStack::PopAndDestroy(title);
            CleanupStack::PopAndDestroy(tempTitle);
            }
        else if (attr == KGlxMediaCollectionPluginSpecificSelectMediaPopupTitle)
            {
            HBufC* title = LoadLocalizedStringLC(KResourceFile, R_ALBUM_POPUP_TITLE);
            aResponse->SetTextValueL(attr, *title);  
            CleanupStack::PopAndDestroy(title); 
            }
        else if (attr == KGlxMediaCollectionPluginSpecificNewMediaItemTitle)
            {
            HBufC* title = LoadLocalizedStringLC(KResourceFile, R_ALBUM_ITEM_TITLE);
            aResponse->SetTextValueL(attr, *title);  
            CleanupStack::PopAndDestroy(title); 
            }
        else if (attr == KGlxMediaCollectionPluginSpecificDefaultMediaTitle)
            {
            HBufC* title = LoadLocalizedStringLC(KResourceFile, R_ALBUM_DEFAULT_TITLE);
            aResponse->SetTextValueL(attr, *title);  
            CleanupStack::PopAndDestroy(title); 
            }
        else if (attr == KMPXMediaGeneralTitle)
            {
            if( TGlxMediaId(KGlxCollectionRootId) == aMediaId )
                {
                HBufC* title = LoadLocalizedStringLC(KResourceFile, R_ALBUM_GENERAL_TITLE);
                aResponse->SetTextValueL(attr, *title);  
                CleanupStack::PopAndDestroy(title); 
                }
            else
                {
                if( aResponse->IsSupported(KGlxMediaCollectionInternalSystemItemType) )
					{
					if( TGlxMediaId(KCapturedAlbumId) == aMediaId )
						{
						 HBufC* title = HbTextResolverSymbian::LoadLC(KCameraText); 
						 aResponse->SetTextValueL(attr, *title);  
						 CleanupStack::PopAndDestroy(title);						
						}
					else if (TGlxMediaId(KFavoriteAlbumId) == aMediaId  )
						{
						HBufC* title = HbTextResolverSymbian::LoadLC(KMyFavText); 
						aResponse->SetTextValueL(attr, *title);  
						CleanupStack::PopAndDestroy(title);						
						}
					}                                             
                 aResponse->Delete(KGlxMediaCollectionInternalSystemItemType);                    
                }
            }
        }
    }
void FShooterChatStyle::GetResources(TArray<const FSlateBrush*>& OutBrushes) const
{
	TextEntryStyle.GetResources(OutBrushes);

	OutBrushes.Add(&BackingBrush);
}
void FAnimNode_TwoBoneIK::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)
{
	SCOPE_CYCLE_COUNTER(STAT_TwoBoneIK_Eval);

	check(OutBoneTransforms.Num() == 0);

	const FBoneContainer& BoneContainer = MeshBases.GetPose().GetBoneContainer();

	// Get indices of the lower and upper limb bones and check validity.
	bool bInvalidLimb = false;

	FCompactPoseBoneIndex IKBoneCompactPoseIndex = IKBone.GetCompactPoseIndex(BoneContainer);

	const FCompactPoseBoneIndex LowerLimbIndex = BoneContainer.GetParentBoneIndex(IKBoneCompactPoseIndex);
	if (LowerLimbIndex == INDEX_NONE)
	{
		bInvalidLimb = true;
	}

	const FCompactPoseBoneIndex UpperLimbIndex = BoneContainer.GetParentBoneIndex(LowerLimbIndex);
	if (UpperLimbIndex == INDEX_NONE)
	{
		bInvalidLimb = true;
	}

	const bool bInBoneSpace = (EffectorLocationSpace == BCS_ParentBoneSpace) || (EffectorLocationSpace == BCS_BoneSpace);
	const int32 EffectorBoneIndex = bInBoneSpace ? BoneContainer.GetPoseBoneIndexForBoneName(EffectorSpaceBoneName) : INDEX_NONE;
	const FCompactPoseBoneIndex EffectorSpaceBoneIndex = BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(EffectorBoneIndex));

	if (bInBoneSpace && (EffectorSpaceBoneIndex == INDEX_NONE))
	{
		bInvalidLimb = true;
	}

	// If we walked past the root, this controlled is invalid, so return no affected bones.
	if( bInvalidLimb )
	{
		return;
	}

	// Get Local Space transforms for our bones. We do this first in case they already are local.
	// As right after we get them in component space. (And that does the auto conversion).
	// We might save one transform by doing local first...
	const FTransform EndBoneLocalTransform = MeshBases.GetLocalSpaceTransform(IKBoneCompactPoseIndex);

	// Now get those in component space...
	FTransform LowerLimbCSTransform = MeshBases.GetComponentSpaceTransform(LowerLimbIndex);
	FTransform UpperLimbCSTransform = MeshBases.GetComponentSpaceTransform(UpperLimbIndex);
	FTransform EndBoneCSTransform = MeshBases.GetComponentSpaceTransform(IKBoneCompactPoseIndex);

	// Get current position of root of limb.
	// All position are in Component space.
	const FVector RootPos = UpperLimbCSTransform.GetTranslation();
	const FVector InitialJointPos = LowerLimbCSTransform.GetTranslation();
	const FVector InitialEndPos = EndBoneCSTransform.GetTranslation();

	// Transform EffectorLocation from EffectorLocationSpace to ComponentSpace.
	FTransform EffectorTransform(EffectorLocation);
	FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, EffectorTransform, EffectorSpaceBoneIndex, EffectorLocationSpace);

	// This is our reach goal.
	FVector DesiredPos = EffectorTransform.GetTranslation();
	FVector DesiredDelta = DesiredPos - RootPos;
	float DesiredLength = DesiredDelta.Size();

	// Check to handle case where DesiredPos is the same as RootPos.
	FVector	DesiredDir;
	if (DesiredLength < (float)KINDA_SMALL_NUMBER)
	{
		DesiredLength = (float)KINDA_SMALL_NUMBER;
		DesiredDir = FVector(1,0,0);
	}
	else
	{
		DesiredDir = DesiredDelta / DesiredLength;
	}

	// Get joint target (used for defining plane that joint should be in).
	FTransform JointTargetTransform(JointTargetLocation);
	FCompactPoseBoneIndex JointTargetSpaceBoneIndex(INDEX_NONE);

	if (JointTargetLocationSpace == BCS_ParentBoneSpace || JointTargetLocationSpace == BCS_BoneSpace)
	{
		int32 Index = BoneContainer.GetPoseBoneIndexForBoneName(JointTargetSpaceBoneName);
		JointTargetSpaceBoneIndex = BoneContainer.MakeCompactPoseIndex(FMeshPoseBoneIndex(Index));
	}
	
	FAnimationRuntime::ConvertBoneSpaceTransformToCS(SkelComp, MeshBases, JointTargetTransform, JointTargetSpaceBoneIndex, JointTargetLocationSpace);

	FVector	JointTargetPos = JointTargetTransform.GetTranslation();
	FVector JointTargetDelta = JointTargetPos - RootPos;
	const float JointTargetLengthSqr = JointTargetDelta.SizeSquared();

	// Same check as above, to cover case when JointTarget position is the same as RootPos.
	FVector JointPlaneNormal, JointBendDir;
	if (JointTargetLengthSqr < FMath::Square((float)KINDA_SMALL_NUMBER))
	{
		JointBendDir = FVector(0,1,0);
		JointPlaneNormal = FVector(0,0,1);
	}
	else
	{
		JointPlaneNormal = DesiredDir ^ JointTargetDelta;

		// If we are trying to point the limb in the same direction that we are supposed to displace the joint in, 
		// we have to just pick 2 random vector perp to DesiredDir and each other.
		if (JointPlaneNormal.SizeSquared() < FMath::Square((float)KINDA_SMALL_NUMBER))
		{
			DesiredDir.FindBestAxisVectors(JointPlaneNormal, JointBendDir);
		}
		else
		{
			JointPlaneNormal.Normalize();

			// Find the final member of the reference frame by removing any component of JointTargetDelta along DesiredDir.
			// This should never leave a zero vector, because we've checked DesiredDir and JointTargetDelta are not parallel.
			JointBendDir = JointTargetDelta - ((JointTargetDelta | DesiredDir) * DesiredDir);
			JointBendDir.Normalize();
		}
	}

	// Find lengths of upper and lower limb in the ref skeleton.
	// Use actual sizes instead of ref skeleton, so we take into account translation and scaling from other bone controllers.
	float LowerLimbLength = (InitialEndPos - InitialJointPos).Size();
	float UpperLimbLength = (InitialJointPos - RootPos).Size();
	float MaxLimbLength	= LowerLimbLength + UpperLimbLength;

	if (bAllowStretching)
	{
		const float ScaleRange = StretchLimits.Y - StretchLimits.X;
		if( ScaleRange > KINDA_SMALL_NUMBER && MaxLimbLength > KINDA_SMALL_NUMBER )
		{
			const float ReachRatio = DesiredLength / MaxLimbLength;
			const float ScalingFactor = (StretchLimits.Y - 1.f) * FMath::Clamp<float>((ReachRatio - StretchLimits.X) / ScaleRange, 0.f, 1.f);
			if (ScalingFactor > KINDA_SMALL_NUMBER)
			{
				LowerLimbLength *= (1.f + ScalingFactor);
				UpperLimbLength *= (1.f + ScalingFactor);
				MaxLimbLength	*= (1.f + ScalingFactor);
			}
		}
	}

	FVector OutEndPos = DesiredPos;
	FVector OutJointPos = InitialJointPos;

	// If we are trying to reach a goal beyond the length of the limb, clamp it to something solvable and extend limb fully.
	if (DesiredLength > MaxLimbLength)
	{
		OutEndPos = RootPos + (MaxLimbLength * DesiredDir);
		OutJointPos = RootPos + (UpperLimbLength * DesiredDir);
	}
	else
	{
		// So we have a triangle we know the side lengths of. We can work out the angle between DesiredDir and the direction of the upper limb
		// using the sin rule:
		const float TwoAB = 2.f * UpperLimbLength * DesiredLength;

		const float CosAngle = (TwoAB != 0.f) ? ((UpperLimbLength*UpperLimbLength) + (DesiredLength*DesiredLength) - (LowerLimbLength*LowerLimbLength)) / TwoAB : 0.f;

		// If CosAngle is less than 0, the upper arm actually points the opposite way to DesiredDir, so we handle that.
		const bool bReverseUpperBone = (CosAngle < 0.f);

		// If CosAngle is greater than 1.f, the triangle could not be made - we cannot reach the target.
		// We just have the two limbs double back on themselves, and EndPos will not equal the desired EffectorLocation.
		if ((CosAngle > 1.f) || (CosAngle < -1.f))
		{
			// Because we want the effector to be a positive distance down DesiredDir, we go back by the smaller section.
			if (UpperLimbLength > LowerLimbLength)
			{
				OutJointPos = RootPos + (UpperLimbLength * DesiredDir);
				OutEndPos = OutJointPos - (LowerLimbLength * DesiredDir);
			}
			else
			{
				OutJointPos = RootPos - (UpperLimbLength * DesiredDir);
				OutEndPos = OutJointPos + (LowerLimbLength * DesiredDir);
			}
		}
		else
		{
			// Angle between upper limb and DesiredDir
			const float Angle = FMath::Acos(CosAngle);

			// Now we calculate the distance of the joint from the root -> effector line.
			// This forms a right-angle triangle, with the upper limb as the hypotenuse.
			const float JointLineDist = UpperLimbLength * FMath::Sin(Angle);

			// And the final side of that triangle - distance along DesiredDir of perpendicular.
			// ProjJointDistSqr can't be neg, because JointLineDist must be <= UpperLimbLength because appSin(Angle) is <= 1.
			const float ProjJointDistSqr = (UpperLimbLength*UpperLimbLength) - (JointLineDist*JointLineDist);
			// although this shouldn't be ever negative, sometimes Xbox release produces -0.f, causing ProjJointDist to be NaN
			// so now I branch it. 						
			float ProjJointDist = (ProjJointDistSqr>0.f)? FMath::Sqrt(ProjJointDistSqr) : 0.f;
			if( bReverseUpperBone )
			{
				ProjJointDist *= -1.f;
			}

			// So now we can work out where to put the joint!
			OutJointPos = RootPos + (ProjJointDist * DesiredDir) + (JointLineDist * JointBendDir);
		}
	}

	// Update transform for upper bone.
	{
		// Get difference in direction for old and new joint orientations
		FVector const OldDir = (InitialJointPos - RootPos).GetSafeNormal();
		FVector const NewDir = (OutJointPos - RootPos).GetSafeNormal();
		// Find Delta Rotation take takes us from Old to New dir
		FQuat const DeltaRotation = FQuat::FindBetweenNormals(OldDir, NewDir);
		// Rotate our Joint quaternion by this delta rotation
		UpperLimbCSTransform.SetRotation( DeltaRotation * UpperLimbCSTransform.GetRotation() );
		// And put joint where it should be.
		UpperLimbCSTransform.SetTranslation( RootPos );

		// Order important. First bone is upper limb.
		OutBoneTransforms.Add( FBoneTransform(UpperLimbIndex, UpperLimbCSTransform) );
	}

	// Update transform for lower bone.
	{
		// Get difference in direction for old and new joint orientations
		FVector const OldDir = (InitialEndPos - InitialJointPos).GetSafeNormal();
		FVector const NewDir = (OutEndPos - OutJointPos).GetSafeNormal();

		// Find Delta Rotation take takes us from Old to New dir
		FQuat const DeltaRotation = FQuat::FindBetweenNormals(OldDir, NewDir);
		// Rotate our Joint quaternion by this delta rotation
		LowerLimbCSTransform.SetRotation( DeltaRotation * LowerLimbCSTransform.GetRotation() );
		// And put joint where it should be.
		LowerLimbCSTransform.SetTranslation( OutJointPos );

		// Order important. Second bone is lower limb.
		OutBoneTransforms.Add( FBoneTransform(LowerLimbIndex, LowerLimbCSTransform) );
	}

	// Update transform for end bone.
	{
		if( bTakeRotationFromEffectorSpace )
		{
			EndBoneCSTransform.SetRotation( EffectorTransform.GetRotation() );
		}
		else if( bMaintainEffectorRelRot )
		{
			EndBoneCSTransform = EndBoneLocalTransform * LowerLimbCSTransform;
		}

		// Set correct location for end bone.
		EndBoneCSTransform.SetTranslation(OutEndPos);

		// Order important. Third bone is End Bone.
		OutBoneTransforms.Add(FBoneTransform(IKBoneCompactPoseIndex, EndBoneCSTransform));
	}

	// Make sure we have correct number of bones
	check(OutBoneTransforms.Num() == 3);
}
Example #23
0
FPlot ParsePlot(int32 nPlotID)
{
	FString sValue;

	FString sPlot = FString::FromInt(nPlotID);

	FString aFullPath = FPaths::GameDevelopersDir();
	aFullPath += "Source/JSON/PLO/";
	aFullPath += *sPlot;
	aFullPath += ".json";
	FString JsonStr;
	FFileHelper::LoadFileToString(JsonStr, *aFullPath);

	TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonStr);
	TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());

	FPlot plot;

	if (FJsonSerializer::Deserialize(JsonReader, JsonObject) && JsonObject.IsValid())
	{
		plot.ResRefID = nPlotID;

		TMap<FString, TSharedPtr<FJsonValue>> JsonValuesMap = JsonObject->Values;
		TSharedPtr<FJsonValue> rootValues;
		JsonValuesMap.RemoveAndCopyValue("Resource", rootValues);
		TSharedPtr<FJsonObject> rootObject = rootValues->AsObject();

		TMap<FString, TSharedPtr<FJsonValue>> rootValuesMap = rootObject->Values;
		TSharedPtr<FJsonValue> agentValues;
		rootValuesMap.RemoveAndCopyValue("Agent", agentValues);
		TSharedPtr<FJsonObject> agentObject = agentValues->AsObject();

		TMap<FString, TSharedPtr<FJsonValue>> agentValuesMap = agentObject->Values;

		for (auto const& y : agentValuesMap)
		{
			if (y.Key == "ResRefName")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.ResRefName = sValue;
			}
			if (y.Key == "LocalCopy")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.LocalCopy = sValue == "False" ? false : true;
			}
			if (y.Key == "Name")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.Name = sValue;
			}
			if (y.Key == "NameStringID")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.NameStringID = FCString::Atoi(*sValue);
			}
			if (y.Key == "NameRequiresReTranslation")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.NameRequiresReTranslation = sValue == "False" ? false : true;
			}
			if (y.Key == "GUID")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.GUID = sValue;
			}
			if (y.Key == "ScriptURI")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.ScriptURI = FCString::Atoi(*sValue);
			}
			if (y.Key == "Priority")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.Priority = FCString::Atoi(*sValue);
			}
			if (y.Key == "JournalImage")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.JournalImage = sValue;
			}
			if (y.Key == "ParentPlotURI")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.ParentPlotURI = FCString::Atoi(*sValue);
			}
			if (y.Key == "EntryType")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.EntryType = FCString::Atoi(*sValue);
			}
			if (y.Key == "AllowPausing")
			{
				y.Value.Get()->TryGetString(sValue);
				plot.AllowPausing = sValue == "False" ? false : true;
			}
		}

		TSharedPtr<FJsonValue> StatusListValues;
		agentValuesMap.RemoveAndCopyValue("StatusList", StatusListValues);
		TSharedPtr<FJsonObject> StatusListObject = StatusListValues->AsObject();

		TArray<TSharedPtr<FJsonValue>> StatusArray = StatusListObject->GetArrayField("Agent");

		FPlotNode statusNode;

		if (StatusArray.Num() > 0)
		{
			int32 counter = 0;
			do {
				TSharedPtr<FJsonValue> StatusValue = StatusArray[counter];
				TSharedPtr<FJsonObject> StatusObject = StatusValue->AsObject();

				TMap<FString, TSharedPtr<FJsonValue>> StatusValuesMap = StatusObject->Values;
				for (auto const& x : StatusValuesMap)
				{
					if (x.Key == "Flag")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.Flag = FCString::Atoi64(*sValue);
					}
					if (x.Key == "Name")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.Name = sValue;
					}
					if (x.Key == "Final")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.Final = sValue == "False" ? false : true;
					}
					if (x.Key == "Repeatable")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.Repeatable = sValue == "False" ? false : true;
					}
					if (x.Key == "JournalText")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.JournalText = sValue;
					}
					if (x.Key == "JournalTextStringID")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.JournalTextStringID = FCString::Atoi(*sValue);
					}
					if (x.Key == "JournalTextRequiresReTranslation")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.JournalTextRequiresReTranslation = sValue == "False" ? false : true;
					}
					if (x.Key == "RewardID")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.RewardID = FCString::Atoi(*sValue);
					}
					if (x.Key == "Comment")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.Comment = sValue;
					}
					if (x.Key == "DefaultValue")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.DefaultValue = FCString::Atoi(*sValue);
					}
					if (x.Key == "AreaLocationTag")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.AreaLocationTag = sValue;
					}
					if (x.Key == "OfferID")
					{
						x.Value.Get()->TryGetString(sValue);
						statusNode.OfferID = FCString::Atoi(*sValue);
					}
				}

				//update Flag with pattern ResRefID+"000"+Flag
				statusNode.Flag = PlotFlagConversion(plot.ResRefID, statusNode.Flag);

				FPlotElement ePlot;
				ePlot.pNode = statusNode;
				ePlot.pValue = 0; //false by default
				plot.StatusList.Add(ePlot);

				counter++;
			} while (counter < StatusArray.Num());
		}
#ifdef DEBUG
		LogWarning("Plot " + IntToString(nPlotID) + " parsed!!");
#endif // DEBUG

		//TODO PlotAssistInfoList
		GetParty()->Plots.Add(plot);
	}
	else {
#ifdef DEBUG
		LogError("Not Deserialized" + aFullPath);
#endif
	}
	return plot;
}
void FEQSSceneProxy::CollectEQSData(const FEnvQueryResult* ResultItems, const FEnvQueryInstance* QueryInstance, float HighlightRangePct, bool ShouldDrawFailedItems, TArray<FSphere>& Spheres, TArray<FText3d>& Texts, TArray<EQSDebug::FDebugHelper>& DebugItems)
{
	if (ResultItems == NULL)
	{
		if (QueryInstance == NULL)
		{
			return;
		}
		else
		{
			ResultItems = QueryInstance;
		}
	}

	// using "mid-results" requires manual normalization
	const bool bUseMidResults = QueryInstance && (QueryInstance->Items.Num() < QueryInstance->DebugData.DebugItems.Num());
	// no point in checking if QueryInstance != null since bUseMidResults == true guarantees that, PVS-Studio doesn't
	// understand that invariant though, and we need to disable V595:
	const TArray<FEnvQueryItem>& Items = bUseMidResults ? QueryInstance->DebugData.DebugItems : ResultItems->Items; //-V595
	const TArray<uint8>& RawData = bUseMidResults ? QueryInstance->DebugData.RawData : ResultItems->RawData;
	const int32 ItemCountLimit = FMath::Clamp(Items.Num(), 0, EQSMaxItemsDrawn);
	const bool bNoTestsPerformed = QueryInstance != NULL && QueryInstance->CurrentTest <= 0;
	
	const bool bSingleItemResult = QueryInstance != NULL && QueryInstance->DebugData.bSingleItemResult;

	float MinScore = 0.f;
	float MaxScore = -BIG_NUMBER;
	if (bUseMidResults || HighlightRangePct < 1.0f)
	{
		const FEnvQueryItem* ItemInfo = Items.GetData();
		for (int32 ItemIndex = 0; ItemIndex < Items.Num(); ItemIndex++, ItemInfo++)
		{
			if (ItemInfo->IsValid())
			{
				MinScore = FMath::Min(MinScore, ItemInfo->Score);
				MaxScore = FMath::Max(MaxScore, ItemInfo->Score);
			}
		}
	}
	
	const float ScoreNormalizer = bUseMidResults && (MaxScore != MinScore) ? 1.f / (MaxScore - MinScore) : 1.f;
	const float HighlightThreshold = (HighlightRangePct < 1.0f) ? (MaxScore * HighlightRangePct) : FLT_MAX;

	if (bSingleItemResult == false)
	{
		for (int32 ItemIndex = 0; ItemIndex < ItemCountLimit; ++ItemIndex)
		{
			if (Items[ItemIndex].IsValid())
			{
				const float Score = bNoTestsPerformed ? 1 : Items[ItemIndex].Score * ScoreNormalizer;
				const bool bLowRadius = (HighlightThreshold < FLT_MAX) && (bNoTestsPerformed || (Items[ItemIndex].Score < HighlightThreshold));
				const float Radius = ItemDrawRadius.X * (bLowRadius ? 0.2f : 1.0f);
				const FVector Loc = FEQSRenderingHelper::ExtractLocation(ResultItems->ItemType, RawData, Items, ItemIndex);
				Spheres.Add(FSphere(Radius, Loc, bNoTestsPerformed == false
					? FLinearColor(FColor::MakeRedToGreenColorFromScalar(Score)) 
					: FLinearColor(0.2, 1.0, 1.0, 1)));

				DebugItems.Add(EQSDebug::FDebugHelper(Loc, Radius));

				const FString Label = bNoTestsPerformed ? TEXT("") : FString::Printf(TEXT("%.2f"), Score);
				Texts.Add(FText3d(Label, Loc, FLinearColor::White));
			}
		}
	}
	else if (ItemCountLimit > 0)
	{
		if (Items[0].IsValid())
		{
			const float Score = Items[0].Score * ScoreNormalizer;
			const bool bLowRadius = false;
			const float Radius = ItemDrawRadius.X * (bLowRadius ? 0.2f : 1.0f);
			const FVector Loc = FEQSRenderingHelper::ExtractLocation(ResultItems->ItemType, RawData, Items, 0);
			Spheres.Add(FSphere(Radius, Loc, FLinearColor(0.0, 1.0, 0.12, 1)));

			DebugItems.Add(EQSDebug::FDebugHelper(Loc, Radius));

			const FString Label = FString::Printf(TEXT("Winner %.2f"), Score);
			Texts.Add(FText3d(Label, Loc, FLinearColor::White));
		}

		for (int32 ItemIndex = 1; ItemIndex < ItemCountLimit; ++ItemIndex)
		{
			if (Items[ItemIndex].IsValid())
			{
				const float Score = bNoTestsPerformed ? 1 : Items[ItemIndex].Score * ScoreNormalizer;
				const bool bLowRadius = (HighlightThreshold < FLT_MAX) && (bNoTestsPerformed || (Items[ItemIndex].Score < HighlightThreshold));
				const float Radius = ItemDrawRadius.X * (bLowRadius ? 0.2f : 1.0f);
				const FVector Loc = FEQSRenderingHelper::ExtractLocation(ResultItems->ItemType, RawData, Items, ItemIndex);
				Spheres.Add(FSphere(Radius, Loc, FLinearColor(0.0, 0.2, 0.025, 1)));

				DebugItems.Add(EQSDebug::FDebugHelper(Loc, Radius));
				
				const FString Label = bNoTestsPerformed ? TEXT("") : FString::Printf(TEXT("%.2f"), Score);
				Texts.Add(FText3d(Label, Loc, FLinearColor::White));
			}
		}
	}

	if (ShouldDrawFailedItems && QueryInstance)
	{
		const FEQSQueryDebugData& InstanceDebugData = QueryInstance->DebugData;
		const TArray<FEnvQueryItem>& DebugQueryItems = InstanceDebugData.DebugItems;
		const TArray<FEnvQueryItemDetails>& Details = InstanceDebugData.DebugItemDetails;

		const int32 DebugItemCountLimit = DebugQueryItems.Num() == Details.Num() ? FMath::Clamp(DebugQueryItems.Num(), 0, EQSMaxItemsDrawn) : 0;

		for (int32 ItemIndex = 0; ItemIndex < DebugItemCountLimit; ++ItemIndex)
		{
			if (DebugQueryItems[ItemIndex].IsValid())
			{
				continue;
			}

			const float Score = bNoTestsPerformed ? 1 : Items[ItemIndex].Score * ScoreNormalizer;
			const bool bLowRadius = (HighlightThreshold < FLT_MAX) && (bNoTestsPerformed || (Items[ItemIndex].Score < HighlightThreshold));
			const float Radius = ItemDrawRadius.X * (bLowRadius ? 0.2f : 1.0f);
			const FVector Loc = FEQSRenderingHelper::ExtractLocation(QueryInstance->ItemType, InstanceDebugData.RawData, DebugQueryItems, ItemIndex);
			Spheres.Add(FSphere(Radius, Loc, FLinearColor(0.0, 0.0, 0.6, 0.6)));

			auto& DebugHelper = DebugItems[DebugItems.Add(EQSDebug::FDebugHelper(Loc, Radius))];
			DebugHelper.AdditionalInformation = Details[ItemIndex].FailedDescription;
			if (Details[ItemIndex].FailedTestIndex != INDEX_NONE)
			{
				DebugHelper.FailedTestIndex = Details[ItemIndex].FailedTestIndex;
				DebugHelper.FailedScore = Details[ItemIndex].TestResults[DebugHelper.FailedTestIndex];

				const FString Label = InstanceDebugData.PerformedTestNames[DebugHelper.FailedTestIndex] + FString::Printf(TEXT("(%d)"), DebugHelper.FailedTestIndex);
				Texts.Add(FText3d(Label, Loc, FLinearColor::White));
			}
		}
	}
}
	bool Save(const FString& HeaderDirPath, const FString& CppDirPath)
	{
		if (!Blueprint.IsValid())
		{
			ErrorString += LOCTEXT("InvalidBlueprint", "Invalid Blueprint\n").ToString();
			return false;
		}

		const int WorkParts = 3 + (4 * DependentObjects.Num()) + (2 * UnconvertedNeededClasses.Num());
		FScopedSlowTask SlowTask(WorkParts, LOCTEXT("GeneratingCppFiles", "Generating C++ files.."));
		SlowTask.MakeDialog();

		IBlueprintCompilerCppBackendModule& CodeGenBackend = (IBlueprintCompilerCppBackendModule&)IBlueprintCompilerCppBackendModule::Get();

		TArray<FString> CreatedFiles;
		for(auto Obj : DependentObjects)
		{
			SlowTask.EnterProgressFrame();

			TSharedPtr<FString> HeaderSource(new FString());
			TSharedPtr<FString> CppSource(new FString());
			FBlueprintNativeCodeGenUtils::GenerateCppCode(Obj, HeaderSource, CppSource);
			SlowTask.EnterProgressFrame();

			const FString BackendBaseFilename = CodeGenBackend.ConstructBaseFilename(Obj);

			const FString FullHeaderFilename = FPaths::Combine(*HeaderDirPath, *(BackendBaseFilename + TEXT(".h")));
			const bool bHeaderSaved = FFileHelper::SaveStringToFile(*HeaderSource, *FullHeaderFilename);
			if (!bHeaderSaved)
			{
				ErrorString += FString::Printf(*LOCTEXT("HeaderNotSaved", "Header file wasn't saved. Check log for details. %s\n").ToString(), *Obj->GetPathName());
			}
			else
			{
				CreatedFiles.Add(FullHeaderFilename);
			}

			SlowTask.EnterProgressFrame();
			if (!CppSource->IsEmpty())
			{
				const FString NewCppFilename = FPaths::Combine(*CppDirPath, *(BackendBaseFilename + TEXT(".cpp")));
				const bool bCppSaved = FFileHelper::SaveStringToFile(*CppSource, *NewCppFilename);
				if (!bCppSaved)
				{
					ErrorString += FString::Printf(*LOCTEXT("CppNotSaved", "Cpp file wasn't saved. Check log for details. %s\n").ToString(), *Obj->GetPathName());
				}
				else
				{
					CreatedFiles.Add(NewCppFilename);
				}
			}
		}

		for (auto BPGC : UnconvertedNeededClasses)
		{
			SlowTask.EnterProgressFrame();

			IKismetCompilerInterface& Compiler = FModuleManager::LoadModuleChecked<IKismetCompilerInterface>(KISMET_COMPILER_MODULENAME);
			const FString HeaderSource = Compiler.GenerateCppWrapper(BPGC);

			SlowTask.EnterProgressFrame();

			const FString BackendBaseFilename = CodeGenBackend.ConstructBaseFilename(BPGC);

			const FString FullHeaderFilename = FPaths::Combine(*HeaderDirPath, *(BackendBaseFilename + TEXT(".h")));
			const bool bHeaderSaved = FFileHelper::SaveStringToFile(HeaderSource, *FullHeaderFilename);
			if (!bHeaderSaved)
			{
				ErrorString += FString::Printf(*LOCTEXT("HeaderNotSaved", "Header file wasn't saved. Check log for details. %s\n").ToString(), *BPGC->GetPathName());
			}
			else
			{
				CreatedFiles.Add(FullHeaderFilename);
			}
		}

		SlowTask.EnterProgressFrame();

		bool bGenerateProjectFiles = true;
		{
			bool bProjectHadCodeFiles = false;
			{
				TArray<FString> OutProjectCodeFilenames;
				IFileManager::Get().FindFilesRecursive(OutProjectCodeFilenames, *FPaths::GameSourceDir(), TEXT("*.h"), true, false, false);
				IFileManager::Get().FindFilesRecursive(OutProjectCodeFilenames, *FPaths::GameSourceDir(), TEXT("*.cpp"), true, false, false);
				bProjectHadCodeFiles = OutProjectCodeFilenames.Num() > 0;
			}

			TArray<FString> CreatedFilesForExternalAppRead;
			CreatedFilesForExternalAppRead.Reserve(CreatedFiles.Num());
			for (const FString& CreatedFile : CreatedFiles)
			{
				CreatedFilesForExternalAppRead.Add(IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*CreatedFile));
			}

			// First see if we can avoid a full generation by adding the new files to an already open project
			if (bProjectHadCodeFiles && FSourceCodeNavigation::AddSourceFiles(CreatedFilesForExternalAppRead))
			{
				// We successfully added the new files to the solution, but we still need to run UBT with -gather to update any UBT makefiles
				if (FDesktopPlatformModule::Get()->InvalidateMakefiles(FPaths::RootDir(), FPaths::GetProjectFilePath(), GWarn))
				{
					// We managed the gather, so we can skip running the full generate
					bGenerateProjectFiles = false;
				}
			}
		}

		SlowTask.EnterProgressFrame();

		bool bProjectFileUpdated = true;
		if (bGenerateProjectFiles)
		{
			// Generate project files if we happen to be using a project file.
			if (!FDesktopPlatformModule::Get()->GenerateProjectFiles(FPaths::RootDir(), FPaths::GetProjectFilePath(), GWarn))
			{
				ErrorString += LOCTEXT("FailedToGenerateProjectFiles", "Failed to generate project files.").ToString();
				bProjectFileUpdated = false;
			}
		}

		return ErrorString.IsEmpty();
	}
void SGameplayTagQueryWidget::Construct(const FArguments& InArgs, const TArray<FEditableGameplayTagQueryDatum>& EditableTagQueries)
{
	ensure(EditableTagQueries.Num() > 0);
	TagQueries = EditableTagQueries;

	bReadOnly = InArgs._ReadOnly;
	bAutoSave = InArgs._AutoSave;
	OnSaveAndClose = InArgs._OnSaveAndClose;
	OnCancel = InArgs._OnCancel;
	OnQueryChanged = InArgs._OnQueryChanged;

	// Tag the assets as transactional so they can support undo/redo
	for (int32 AssetIdx = 0; AssetIdx < TagQueries.Num(); ++AssetIdx)
	{
		UObject* TagQueryOwner = TagQueries[AssetIdx].TagQueryOwner.Get();
		if (TagQueryOwner)
		{
			TagQueryOwner->SetFlags(RF_Transactional);
		}
	}

	// build editable query object tree from the runtime query data
	UEditableGameplayTagQuery* const EQ = CreateEditableQuery(*TagQueries[0].TagQuery);
	EditableQuery = EQ;

	// create details view for the editable query object
	FDetailsViewArgs ViewArgs;
	ViewArgs.bAllowSearch = false;
	ViewArgs.bHideSelectionTip = true;
	ViewArgs.bShowActorLabel = false;
	
	FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
	Details = PropertyModule.CreateDetailView(ViewArgs);
	Details->SetObject(EQ);
	Details->OnFinishedChangingProperties().AddSP(this, &SGameplayTagQueryWidget::OnFinishedChangingProperties);

	ChildSlot
	[
		SNew(SBorder)
		.BorderImage(FEditorStyle::GetBrush("ToolPanel.GroupBorder"))
		[
			SNew(SVerticalBox)
			+ SVerticalBox::Slot()
			.AutoHeight()
			.VAlign(VAlign_Top)
			[
				SNew(SHorizontalBox)
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SButton)
					.IsEnabled(!bReadOnly)
					.Visibility(this, &SGameplayTagQueryWidget::GetSaveAndCloseButtonVisibility)
					.OnClicked(this, &SGameplayTagQueryWidget::OnSaveAndCloseClicked)
					.Text(LOCTEXT("GameplayTagQueryWidget_SaveAndClose", "Save and Close"))
				]
				+ SHorizontalBox::Slot()
				.AutoWidth()
				[
					SNew(SButton)
					.Visibility(this, &SGameplayTagQueryWidget::GetCancelButtonVisibility)
					.OnClicked(this, &SGameplayTagQueryWidget::OnCancelClicked)
					.Text(LOCTEXT("GameplayTagQueryWidget_Cancel", "Close Without Saving"))
				]
			]
			// to delete!
			+ SVerticalBox::Slot()
			[
				Details.ToSharedRef()
			]
		]
	];
}
	void QueryConnectedDevices()
	{
		// grab the list of devices via adb
		FString StdOut;
		if (!ExecuteAdbCommand(TEXT("devices -l"), &StdOut, nullptr))
		{
			return;
		}

		// separate out each line
		TArray<FString> DeviceStrings;
		StdOut = StdOut.Replace(TEXT("\r"), TEXT("\n"));
		StdOut.ParseIntoArray(&DeviceStrings, TEXT("\n"), true);

		// a list containing all devices found this time, so we can remove anything not in this list
		TArray<FString> CurrentlyConnectedDevices;

		for (int32 StringIndex = 0; StringIndex < DeviceStrings.Num(); ++StringIndex)
		{
			const FString& DeviceString = DeviceStrings[StringIndex];

			// skip over non-device lines
			if (DeviceString.StartsWith("* ") || DeviceString.StartsWith("List "))
			{
				continue;
			}

			// grab the device serial number
			int32 TabIndex;

			if (!DeviceString.FindChar(TCHAR(' '), TabIndex))
			{
				continue;
			}

			FAndroidDeviceInfo NewDeviceInfo;

			NewDeviceInfo.SerialNumber = DeviceString.Left(TabIndex);
			const FString DeviceState = DeviceString.Mid(TabIndex + 1).Trim();

			NewDeviceInfo.bUnauthorizedDevice = DeviceState == TEXT("unauthorized");

			// add it to our list of currently connected devices
			CurrentlyConnectedDevices.Add(NewDeviceInfo.SerialNumber);

			// move on to next device if this one is already a known device
			if (DeviceMap.Contains(NewDeviceInfo.SerialNumber))
			{
				continue;
			}

			if (NewDeviceInfo.bUnauthorizedDevice)
			{
				NewDeviceInfo.DeviceName = TEXT("Unauthorized - enable USB debugging");
			}
			else
			{
				// grab the Android version
				const FString AndroidVersionCommand = FString::Printf(TEXT("-s %s shell getprop ro.build.version.release"), *NewDeviceInfo.SerialNumber);
				if (!ExecuteAdbCommand(*AndroidVersionCommand, &NewDeviceInfo.HumanAndroidVersion, nullptr))
				{
					continue;
				}
				NewDeviceInfo.HumanAndroidVersion = NewDeviceInfo.HumanAndroidVersion.Replace(TEXT("\r"), TEXT("")).Replace(TEXT("\n"), TEXT(""));
				NewDeviceInfo.HumanAndroidVersion.Trim().TrimTrailing();

				// grab the Android SDK version
				const FString SDKVersionCommand = FString::Printf(TEXT("-s %s shell getprop ro.build.version.sdk"), *NewDeviceInfo.SerialNumber);
				FString SDKVersionString;
				if (!ExecuteAdbCommand(*SDKVersionCommand, &SDKVersionString, nullptr))
				{
					continue;
				}
				NewDeviceInfo.SDKVersion = FCString::Atoi(*SDKVersionString);
				if (NewDeviceInfo.SDKVersion <= 0)
				{
					NewDeviceInfo.SDKVersion = INDEX_NONE;
				}

				// get the GL extensions string (and a bunch of other stuff)
				const FString ExtensionsCommand = FString::Printf(TEXT("-s %s shell dumpsys SurfaceFlinger"), *NewDeviceInfo.SerialNumber);
				if (!ExecuteAdbCommand(*ExtensionsCommand, &NewDeviceInfo.GLESExtensions, nullptr))
				{
					continue;
				}

				// grab the GL ES version
				FString GLESVersionString;
				const FString GLVersionCommand = FString::Printf(TEXT("-s %s shell getprop ro.opengles.version"), *NewDeviceInfo.SerialNumber);
				if (!ExecuteAdbCommand(*GLVersionCommand, &GLESVersionString, nullptr))
				{
					continue;
				}
				NewDeviceInfo.GLESVersion = FCString::Atoi(*GLESVersionString);

				// parse the device model
				FParse::Value(*DeviceString, TEXT("model:"), NewDeviceInfo.Model);
				if (NewDeviceInfo.Model.IsEmpty())
				{
					FString ModelCommand = FString::Printf(TEXT("-s %s shell getprop ro.product.model"), *NewDeviceInfo.SerialNumber);
					FString RoProductModel;
					ExecuteAdbCommand(*ModelCommand, &RoProductModel, nullptr);
					const TCHAR* Ptr = *RoProductModel;
					FParse::Line(&Ptr, NewDeviceInfo.Model);
				}

				// parse the device name
				FParse::Value(*DeviceString, TEXT("device:"), NewDeviceInfo.DeviceName);
				if (NewDeviceInfo.DeviceName.IsEmpty())
				{
					FString DeviceCommand = FString::Printf(TEXT("-s %s shell getprop ro.product.device"), *NewDeviceInfo.SerialNumber);
					FString RoProductDevice;
					ExecuteAdbCommand(*DeviceCommand, &RoProductDevice, nullptr);
					const TCHAR* Ptr = *RoProductDevice;
					FParse::Line(&Ptr, NewDeviceInfo.DeviceName);
				}
			}

			// add the device to the map
			{
				FScopeLock ScopeLock(DeviceMapLock);

				FAndroidDeviceInfo& SavedDeviceInfo = DeviceMap.Add(NewDeviceInfo.SerialNumber);
				SavedDeviceInfo = NewDeviceInfo;
			}
		}

		// loop through the previously connected devices list and remove any that aren't still connected from the updated DeviceMap
		TArray<FString> DevicesToRemove;

		for (auto It = DeviceMap.CreateConstIterator(); It; ++It)
		{
			if (!CurrentlyConnectedDevices.Contains(It.Key()))
			{
				DevicesToRemove.Add(It.Key());
			}
		}

		{
			// enter the critical section and remove the devices from the map
			FScopeLock ScopeLock(DeviceMapLock);

			for (auto It = DevicesToRemove.CreateConstIterator(); It; ++It)
			{
				DeviceMap.Remove(*It);
			}
		}
	}
FGameplayAbilityTargetDataHandle FGameplayAbilityTargetingLocationInfo::MakeTargetDataHandleFromHitResult(TWeakObjectPtr<UGameplayAbility> Ability, const FHitResult& HitResult) const
{
	TArray<FHitResult> HitResults;
	HitResults.Add(HitResult);
	return MakeTargetDataHandleFromHitResults(Ability, HitResults);
}
Example #29
0
void FEdModeGeometry::GetFromSource()
{
	GWarn->BeginSlowTask( NSLOCTEXT("EditorModes", "GeometryMode-BeginRebuildingBSPTask", "Rebuilding BSP"), false);

	TArray<HGeomMidPoints> GeomData;

	// Go through each brush and update its components before updating below
	for( int32 i=0; i<GeomObjects.Num(); i++ )
	{
		FGeomObject* GeomObject = GeomObjects[i];
		if(GeomObject && GeomObject->ActualBrush)
		{
#ifdef BSP_RESELECT
			// Cache any information that'll help us reselect the object after it's reconstructed
			CacheSelectedData( GeomData, *GeomObject );
#endif // BSP_RESELECT
			GeomObject->ActualBrush->UnregisterAllComponents();
			if (GeomObject->ActualBrush->GetWorld())
			{
				GeomObject->ActualBrush->RegisterAllComponents();
			}
			delete GeomObject;
		}		
	}
	GeomObjects.Empty();

	TArray<FGeomBase*> SelectedGeom;

	// Notify the selected actors that they have been moved.
	bool bFound = true;
	for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
	{
		AActor* Actor = static_cast<AActor*>( *It );
		checkSlow( Actor->IsA(AActor::StaticClass()) );

		ABrush* BrushActor = Cast< ABrush >( Actor );
		if ( BrushActor )
		{
			if( BrushActor->Brush != NULL )
			{
				FGeomObject* GeomObject			= new FGeomObject();
				GeomObject->SetParentObjectIndex( GeomObjects.Add( GeomObject ) );
				GeomObject->ActualBrush			= BrushActor;
				GeomObject->GetFromSource();
#ifdef BSP_RESELECT
				// Attempt to find all the previously selected geometry on this object if everything has gone OK so far
				if ( bFound && !FindFromCache( GeomData, *GeomObject, SelectedGeom ) )
				{
#ifdef BSP_RESELECT__ALL_OR_NOTHING
					// If it didn't succeed, don't attempt to reselect anything as the user will only end up moving part of their previous selection
					UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find all previously selected geometry data, resetting selection" ) );
					SelectedGeom.Empty();
					GeomData.Empty();
					bFound = false;
#endif // BSP_RESELECT__ALL_OR_NOTHING
				}
#endif // BSP_RESELECT
			}
		}
	}

#ifdef BSP_RESELECT
	// Reselect anything that came close to the cached midpoints
	SelectCachedData( SelectedGeom );
#endif // BSP_RESELECT

	GWarn->EndSlowTask();
}
void GenerateEncounterFrequency (CUniverse &Universe, CXMLElement *pCmdLine)
	{
	enum ETypes
		{
		outputFreq,
		outputFillLocations,
		};

	int i, j;

	//	Options

	int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1);
	bool bLogo = !pCmdLine->GetAttributeBool(CONSTLIT("noLogo"));
	bool bAll = pCmdLine->GetAttributeBool(CONSTLIT("all"));

	bool bRawData = pCmdLine->GetAttributeBool(CONSTLIT("rawData"));
	
	ETypes iType;
	if (pCmdLine->GetAttributeBool(CONSTLIT("fillLocations")))
		iType = outputFillLocations;
	else
		iType = outputFreq;

	//	Additional columns

	TArray<CString> Cols;
	for (i = 0; i < pCmdLine->GetAttributeCount(); i++)
		{
		CString sAttrib = pCmdLine->GetAttributeName(i);

		if (!IsMainCommandParam(sAttrib)
				&& !strEquals(sAttrib, CONSTLIT("count"))
				&& !strEquals(sAttrib, CONSTLIT("fillLocations"))
				&& !strEquals(sAttrib, CONSTLIT("rawData"))
				&& !strEquals(sAttrib, CONSTLIT("encounterfreq")))
			{
			CString sValue = pCmdLine->GetAttribute(i);
			
			if (!strEquals(sValue, CONSTLIT("true")))
				Cols.Insert(strPatternSubst(CONSTLIT("%s:%s"), sAttrib, sValue));
			else
				Cols.Insert(sAttrib);
			}
		}

	//	Generate systems for multiple games

	CSystemCreateStats Stats;
	for (i = 0; i < iSystemSample; i++)
		{
		if (bLogo)
			printf("pass %d...\n", i+1);

		//	Initialize the game

		CString sError;
		if (Universe.InitGame(0, &sError) != NOERROR)
			{
			printf("%s\n", sError.GetASCIIZPointer());
			return;
			}

		for (j = 0; j < Universe.GetTopologyNodeCount(); j++)
			{
			CTopologyNode *pNode = Universe.GetTopologyNode(j);
			if (pNode->IsEndGame())
				continue;

			//	Create the system

			CSystem *pSystem;
			if (Universe.CreateStarSystem(pNode, &pSystem, NULL, &Stats) != NOERROR)
				{
				printf("ERROR: Unable to create star system.\n");
				return;
				}

			//	Done with old system

			Universe.DestroySystem(pSystem);
			}

		Universe.Reinit();
		}

	//	Output based on type

	if (iType == outputFreq)
		{
		//	Generate a table for each encounter

		TSortMap<CStationType *, SEncounterFreqEntry> EncounterFreq;
		for (i = 0; i < Stats.GetEncounterTableCount(); i++)
			{
			const CSystemCreateStats::SEncounterTable &Table = Stats.GetEncounterTable(i);

			//	Skip if only planets and asteroids

			if (!Table.bHasStation && !bAll)
				continue;

			//	For each entry in the table, add to the frequency table

			for (j = 0; j < Table.Table.GetCount(); j++)
				{
				CStationType *pEncounterType = Table.Table.GetAt(j);
				int iChance = Table.Table.GetChance(j);

				SEncounterFreqEntry *pEntry = EncounterFreq.SetAt(pEncounterType);
				pEntry->iCount += Table.iCount;
				pEntry->iTotalChance += Table.iCount * iChance;

				if (pEntry->pMaxTable == NULL || iChance > pEntry->iMaxChance)
					{
					pEntry->pMaxTable = &Table;
					pEntry->iMaxChance = iChance;
					}

				if (pEntry->pMinTable == NULL || iChance < pEntry->iMinChance)
					{
					pEntry->pMinTable = &Table;
					pEntry->iMinChance = iChance;
					}
				}
			}

		//	Output encounter frequency distribution

		printf("Level\tCategory\tEncounter\tTotal Chances\tAverage Chance\tMin Chance\tMax Chance");
		for (i = 0; i < Cols.GetCount(); i++)
			printf("\t%s", Cols[i].GetASCIIZPointer());
		printf("\n");

		for (i = 0; i < EncounterFreq.GetCount(); i++)
			{
			CStationType *pEncounterType = EncounterFreq.GetKey(i);
			int iAveWhole = EncounterFreq[i].iTotalChance / EncounterFreq[i].iCount;
			int iAveFrac = 1000 * (EncounterFreq[i].iTotalChance % EncounterFreq[i].iCount) / EncounterFreq[i].iCount;

			printf("%d\t%s\t%s\t%d\t%d.%03d\t%d\t%d",
					pEncounterType->GetLevel(),
					pEncounterType->GetDataField(CONSTLIT("category")).GetASCIIZPointer(),
					pEncounterType->GetNounPhrase().GetASCIIZPointer(),
					EncounterFreq[i].iCount,
					iAveWhole,
					iAveFrac,
					EncounterFreq[i].iMinChance,
					EncounterFreq[i].iMaxChance);

			for (j = 0; j < Cols.GetCount(); j++)
				{
				CString sValue = pEncounterType->GetDataField(Cols[j]);
				printf("\t%s", sValue.GetASCIIZPointer());
				}

			printf("\n");
			}

		//	Output raw data

		if (bRawData)
			{
			//	Loop over stats and output tables

			for (i = 0; i < Stats.GetEncounterTableCount(); i++)
				{
				const CSystemCreateStats::SEncounterTable &Table = Stats.GetEncounterTable(i);

				//	Skip if only planets and asteroids

				if (!Table.bHasStation && !bAll)
					continue;

				//	Header

				printf("LEVEL %d (%d location%s)\nSystem Type: %08x\nStations: %s\n", 
						Table.iLevel,
						Table.iCount,
						(Table.iCount == 1 ? "" : "s"),
						Table.pSystemType->GetUNID(),
						Table.sStationCriteria.GetASCIIZPointer());

				//	Location attributes

				printf("Location: ");
				for (j = 0; j < Table.LabelAttribs.GetCount(); j++)
					{
					if (j != 0)
						printf(", ");
					printf(Table.LabelAttribs[j].GetASCIIZPointer());
					}
				printf("\n");

				//	Entries

				for (j = 0; j < Table.Table.GetCount(); j++)
					printf("%s\t%d\n", Table.Table.GetAt(j)->GetNounPhrase().GetASCIIZPointer(), Table.Table.GetChance(j));

				printf("\n");
				}
			}
		}
	else if (iType == outputFillLocations)
		{
		printf("Level\tSystem\tEncounter\tChance\n");

		for (i = 0; i < Stats.GetFillLocationsTableCount(); i++)
			{
			const CSystemCreateStats::SFillLocationsTable &Entry = Stats.GetFillLocationsTable(i);

			for (j = 0; j < Entry.Table.GetCount(); j++)
				{
				int iPercent = (int)(1000.0 * Entry.Table.GetChance(j) / (Metric)Entry.Table.GetTotalChance());

				printf("%d\t%s\t%s\t%d.%d\n",
						Entry.iLevel,
						Entry.sSystemName.GetASCIIZPointer(),
						Entry.Table[j]->GetNounPhrase().GetASCIIZPointer(), 
						iPercent / 10,
						iPercent % 10);
				}
			}
		}
	}