diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..160dffd --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,354 @@ +# BladeSmith Agent Development Guide + +## Project Overview + +BladeSmith is a UE5.6 C++ blacksmith simulation game featuring physics-based metal forging with GPU-accelerated compute shaders and dynamic mesh deformation. + +**Core Technologies:** +- Unreal Engine 5.6 +- Geometry Scripting API +- Custom Compute Shaders (MiceShaders plugin) +- Dynamic Mesh System +- Enhanced Input +- Voxel-based physics simulation + +--- + +## Build Commands + +### Building the Project +```bash +# Build game target (run from UE5 engine directory) +"C:\Program Files\Epic Games\UE_5.6\Engine\Build\BatchFiles\Build.bat" BladeSmith Win64 Development "E:\MiceCola\work\BladeSmith\BladeSmith.uproject" + +# Build editor target +"C:\Program Files\Epic Games\UE_5.6\Engine\Build\BatchFiles\Build.bat" BladeSmithEditor Win64 Development "E:\MiceCola\work\BladeSmith\BladeSmith.uproject" + +# Alternative: Open BladeSmith.sln in Visual Studio +``` + +### Running Tests +UE5 uses the Automation System, not traditional test runners: +- **Editor**: Window → Developer Tools → Automation Sessions +- **Command line**: `UE5Editor.exe BladeSmith.uproject -ExecCmds="Automation RunTests"` +- **Single test**: Run specific test class from Automation Sessions panel + +### Development Workflow +1. Open `BladeSmith.uproject` in UE5.6 editor +2. Use hot reload for C++ changes (Ctrl+F11 in editor) +3. Test via "Play In Editor" (Alt+P) +4. Use Visual Studio for compilation + +--- + +## Code Style Guidelines + +### File Structure +- **Header files (.h)**: Class declarations, forward declarations, USTRUCT/UCLASS definitions +- **Source files (.cpp)**: Implementations, includes in dependency order +- **Shader files (.usf)**: HLSL compute shaders in `Plugins/MiceShaders/Shaders/Private/` + +### Import Ordering + +**Header Files:** +```cpp +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "ProjectModule.generated.h" + +class UForwardDeclaredClass; // Forward declarations +``` + +**Source Files:** +```cpp +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "ClassName.h" +#include "SystemHeader1.h" +#include "SystemHeader2.h" +``` + +**Pattern:** +1. Epic copyright header (required) +2. `#pragma once` guard +3. Core UE5 headers (`CoreMinimal.h` first) +4. Engine framework headers +5. Project headers +6. Forward declarations (headers only) + +### Naming Conventions + +**Classes:** PascalCase with UE5 prefixes +- `ABladeSmithCharacter` - Actor classes (A prefix) +- `UBladeSmithWeaponComponent` - Component classes (U prefix) +- `FDeformationVoxel` - Structs (F prefix) +- `EGameStateEnum` - Enums (E prefix) + +**Functions:** PascalCase +```cpp +public: + void SwingHammer(); + FVector GetHammerHeadLocation() const; + +private: + void PerformHammerHit(); // Private helpers use PascalCase +``` + +**Variables:** camelCase +```cpp +float HammerForce = 1000.0f; +FVector HammerHeadOffset; +UMaterialInstanceDynamic* DynamicMaterialInstance; +TArray TemperatureGrid; +``` + +**Constants:** PascalCase +```cpp +const int32 MaxResolutionPerAxis = 200; +const float DefaultTemperature = 20.0f; +``` + +### Formatting + +**Indentation:** 4 spaces (no tabs) +**Braces:** Allman style - opening brace on new line +```cpp +void ABladeSmithCharacter::Move(const FInputActionValue& Value) +{ + FVector2D MovementVector = Value.Get(); + // implementation +} +``` + +**Line Length:** Under 120 characters, wrap parameters as needed +**Spacing:** Spaces around operators, after commas + +### UE5 Macros and Attributes + +**UPROPERTY Specifiers:** +```cpp +UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category") +UPropertyType* VariableName; + +UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category|Subcategory", meta = (ClampMin = "0.0", ClampMax = "1.0")) +float PropertyWithConstraints; + +UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Category", meta = (AllowPrivateAccess = "true")) +UComponentType* PrivateComponent; +``` + +**UFUNCTION Specifiers:** +```cpp +UFUNCTION(BlueprintCallable, Category = "Category Name") +ReturnType FunctionName(Parameters); + +UFUNCTION(BlueprintImplementableEvent) +void BlueprintEventName(); +``` + +**USTRUCT:** +```cpp +USTRUCT(BlueprintType) +struct FStructName +{ + GENERATED_BODY() + + UPROPERTY() + Type VariableName; +}; +``` + +### Type Annotations + +**UE5 Types (preferred):** +- `TArray` instead of std::vector +- `TMap` instead of std::map +- `TSet` instead of std::unordered_set +- `FVector`, `FVector2D`, `FRotator`, `FQuat` for math +- `FString` for strings (TEXT() macro for string literals) +- `FName` for names, `FText` for localized text +- `float` not double (unless precision critical) +- `int32` not int, `uint8` for bytes +- `bool` for booleans + +**Smart Pointers:** +- Use UE5's garbage collection for UObject-derived classes +- `TSharedPtr` for non-UObject smart pointers +- `TWeakObjectPtr` for weak references to UObjects + +### Error Handling + +**Null Checks:** +```cpp +if (DynamicMeshComp == nullptr) +{ + UE_LOG(LogTemp, Error, TEXT("DynamicMeshComponent not found")); + return; +} +``` + +**Logging:** +```cpp +UE_LOG(LogTemp, Log, TEXT("Temperature: %.1f°C"), Temperature); // Info +UE_LOG(LogTemp, Warning, TEXT("Temperature system disabled")); // Warning +UE_LOG(LogTemp, Error, TEXT("Failed to initialize GPU buffers")); // Error +``` + +**Validation:** +```cpp +if (!IsValid(InputParam)) +{ + return false; +} + +// Early return pattern +if (Condition) +{ + return; +} +``` + +### Documentation + +**Chinese Comments:** Domain-specific logic uses Chinese comments +```cpp +/** 锤子组件 */ +/** 温度体素结构 - 存储单个体素的温度和塑性数据 */ +``` + +**Function Documentation:** +```cpp +/** + * 函数简述 + * @param ParameterName 参数说明 + * @return 返回值说明 + */ +``` + +### Threading and GPU Operations + +**Atomic Flags:** +```cpp +std::atomic bGPUBuffersReady{false}; +``` + +**Render Thread Operations:** +```cpp +ENQUEUE_RENDER_COMMAND(CommandName)( + [Params](FRHICommandListImmediate& RHICmdList) + { + // GPU operations here + } +); +``` + +### Component Structure Pattern + +**Actor Template:** +```cpp +UCLASS() +class BLADESMITH_API AClassName : public AParentClass +{ + GENERATED_BODY() + +public: + AClassName(); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Category") + UComponentType* Component; + + UFUNCTION(BlueprintCallable, Category="Category") + ReturnType PublicFunction(); + +protected: + virtual void BeginPlay() override; + virtual void Tick(float DeltaTime) override; + +private: + void PrivateHelper(); +}; +``` + +--- + +## Module Dependencies + +**BladeSmith.Build.cs:** +- GeometryScriptingCore, GeometryFramework, DynamicMesh +- GeometryCore, GeometryAlgorithms, ModelingComponents +- RenderCore, RHI, Renderer, PhysicsCore +- EnhancedInput, AudioExtensions, AudioMixer +- Custom: MiceShaders (plugin) + +--- + +## Performance Guidelines + +- **Deformation calculations:** <7ms per frame target +- **60 FPS:** Maintain during hammer operations +- **High-poly meshes:** ~100k vertices with GPU acceleration +- **Voxel resolution:** 50x50x50 typical (balance performance/quality) +- **Use RDG (Render Dependency Graph)** for GPU compute operations + +--- + +## Common Patterns + +**Material Parameters:** +```cpp +UMaterialInstanceDynamic* DynMaterial = UMaterialInstanceDynamic::Create(BaseMaterial, this); +DynMaterial->SetScalarParameterValue(TEXT("ParameterName"), Value); +DynMaterial->SetVectorParameterValue(TEXT("VectorParam"), FLinearColor(R,G,B,A)); +DynMaterial->SetTextureParameterValue(TEXT("TextureParam"), Texture); +``` + +**Dynamic Mesh Editing:** +```cpp +UDynamicMesh* DynMesh = DynMeshComp->GetDynamicMesh(); +DynMesh->EditMesh([&](FDynamicMesh3& EditMesh) +{ + for (FVertexID VertexID : EditMesh.VertexIndicesItr()) + { + EditMesh.SetVertex(VertexID, NewPosition); + } +}, EDynamicMeshChangeType::GeneralEdit); +``` + +**Input Binding (Enhanced Input):** +```cpp +if (UEnhancedInputComponent* EnhancedInput = Cast(InputComponent)) +{ + EnhancedInput->BindAction(Action, ETriggerEvent::Triggered, this, &ClassName::Handler); +} +``` + +--- + +## Plugin System + +**MiceShaders Plugin:** +- Custom compute shaders for temperature simulation and deformation +- Located in `Plugins/MiceShaders/` +- Add new shaders: Create `.h` and `.cpp` in Source/MiceShaders, HLSL in Shaders/Private/ +- Use RDG for shader dispatch + +--- + +## Git Workflow + +- **Ignore:** `Binaries/`, `Intermediate/`, `DerivedDataCache/`, `Saved/`, `.vs/`, `.idea/` +- **Commit:** Source/, Content/, Plugins/, Config/, docs/ +- **No binary assets** in Git (use version control for assets) + +--- + +## Documentation + +**Technical docs:** Located in `docs/plans/` +- Reference existing design docs before implementing new features +- Update plans when architecture changes +- Use markdown for design documents