Phase 2A: Procedural Classic Cube Actor — initial implementation
- Added HyperTwistClassicCubeTypes.h with face enum and piece data struct - Added AHyperTwistClassicCubeActor with UProceduralMeshComponent per piece - Generates 26 pieces (6 centers, 12 edges, 8 corners) in 3x3x3 grid - Per-face materials: 6 color slots + internal dark gray - Programmatic fallback unlit materials for each Rubik's face color - Added ProceduralMeshComponent module dependency to Build.cs - Added ProceduralMeshComponent plugin to .uproject
This commit is contained in:
parent
15bb3d9039
commit
6517274fc4
6 changed files with 387 additions and 14 deletions
|
|
@ -0,0 +1,274 @@
|
|||
#include "HyperTwistSimulation/HyperTwistClassicCubeActor.h"
|
||||
#include "Materials/Material.h"
|
||||
#include "Materials/MaterialExpressionConstant3Vector.h"
|
||||
|
||||
AHyperTwistClassicCubeActor::AHyperTwistClassicCubeActor()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("Root"));
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::OnConstruction(const FTransform& Transform)
|
||||
{
|
||||
Super::OnConstruction(Transform);
|
||||
if (bGenerateOnConstruction)
|
||||
{
|
||||
ClearPieces();
|
||||
GenerateCube();
|
||||
}
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
if (!bGenerateOnConstruction)
|
||||
{
|
||||
ClearPieces();
|
||||
GenerateCube();
|
||||
}
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::ClearPieces()
|
||||
{
|
||||
for (UProceduralMeshComponent* Mesh : PieceMeshes)
|
||||
{
|
||||
if (Mesh && Mesh->IsValidLowLevel())
|
||||
{
|
||||
Mesh->DestroyComponent();
|
||||
}
|
||||
}
|
||||
PieceMeshes.Empty();
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::EnsureDefaultMaterials()
|
||||
{
|
||||
if (bDefaultMaterialsCreated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Standard Rubik's cube colors (unlit)
|
||||
const TArray<FLinearColor> Colors = {
|
||||
FLinearColor(1.0f, 1.0f, 1.0f), // Up - White
|
||||
FLinearColor(1.0f, 0.84f, 0.0f), // Down - Yellow
|
||||
FLinearColor(0.0f, 0.62f, 0.27f), // Front - Green
|
||||
FLinearColor(0.0f, 0.27f, 0.68f), // Back - Blue
|
||||
FLinearColor(1.0f, 0.35f, 0.0f), // Left - Orange
|
||||
FLinearColor(0.72f, 0.07f, 0.07f) // Right - Red
|
||||
};
|
||||
|
||||
for (int32 i = 0; i < 6; ++i)
|
||||
{
|
||||
UMaterial* Mat = NewObject<UMaterial>(this, *FString::Printf(TEXT("FaceMat_%d"), i));
|
||||
Mat->SetShadingModel(MSM_Unlit);
|
||||
|
||||
UMaterialExpressionConstant3Vector* ColorNode = NewObject<UMaterialExpressionConstant3Vector>(Mat);
|
||||
ColorNode->Constant = Colors[i];
|
||||
Mat->Expressions.Add(ColorNode);
|
||||
|
||||
Mat->EmissiveColor.Expression = ColorNode;
|
||||
Mat->PostEditChange();
|
||||
|
||||
DefaultFaceMats.Add(Mat);
|
||||
}
|
||||
|
||||
// Internal material - near-black
|
||||
UMaterial* IntMat = NewObject<UMaterial>(this, TEXT("InternalMat"));
|
||||
IntMat->SetShadingModel(MSM_Unlit);
|
||||
UMaterialExpressionConstant3Vector* IntColorNode = NewObject<UMaterialExpressionConstant3Vector>(IntMat);
|
||||
IntColorNode->Constant = FLinearColor(0.05f, 0.05f, 0.05f);
|
||||
IntMat->Expressions.Add(IntColorNode);
|
||||
IntMat->EmissiveColor.Expression = IntColorNode;
|
||||
IntMat->PostEditChange();
|
||||
DefaultInternalMat = IntMat;
|
||||
|
||||
bDefaultMaterialsCreated = true;
|
||||
}
|
||||
|
||||
UMaterialInterface* AHyperTwistClassicCubeActor::GetFaceMaterial(EHyperTwistClassicCubeFace Face)
|
||||
{
|
||||
int32 Index = static_cast<int32>(Face);
|
||||
if (FaceMaterials.IsValidIndex(Index) && FaceMaterials[Index] != nullptr)
|
||||
{
|
||||
return FaceMaterials[Index];
|
||||
}
|
||||
EnsureDefaultMaterials();
|
||||
return DefaultFaceMats.IsValidIndex(Index) ? DefaultFaceMats[Index] : nullptr;
|
||||
}
|
||||
|
||||
UMaterialInterface* AHyperTwistClassicCubeActor::GetInternalMat()
|
||||
{
|
||||
if (InternalMaterial != nullptr)
|
||||
{
|
||||
return InternalMaterial;
|
||||
}
|
||||
EnsureDefaultMaterials();
|
||||
return DefaultInternalMat;
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::GenerateCube()
|
||||
{
|
||||
EnsureDefaultMaterials();
|
||||
|
||||
struct FPieceDef
|
||||
{
|
||||
FVector GridPos;
|
||||
TArray<EHyperTwistClassicCubeFace> Faces;
|
||||
};
|
||||
|
||||
const TArray<FPieceDef> Pieces = {
|
||||
// Centers
|
||||
{FVector(0, 0, 1), {EHyperTwistClassicCubeFace::Up}},
|
||||
{FVector(0, 0, -1), {EHyperTwistClassicCubeFace::Down}},
|
||||
{FVector(0, 1, 0), {EHyperTwistClassicCubeFace::Front}},
|
||||
{FVector(0, -1, 0), {EHyperTwistClassicCubeFace::Back}},
|
||||
{FVector(-1, 0, 0), {EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, 0, 0), {EHyperTwistClassicCubeFace::Right}},
|
||||
// Edges
|
||||
{FVector(0, 1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Front}},
|
||||
{FVector(1, 0, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(0, -1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Back}},
|
||||
{FVector(-1, 0, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(0, 1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Front}},
|
||||
{FVector(1, 0, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(0, -1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Back}},
|
||||
{FVector(-1, 0, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, 1, 0), {EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, 1, 0), {EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, -1, 0), {EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, -1, 0), {EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Left}},
|
||||
// Corners
|
||||
{FVector(1, 1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, 1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, -1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, -1, 1), {EHyperTwistClassicCubeFace::Up, EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, 1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, 1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Front, EHyperTwistClassicCubeFace::Left}},
|
||||
{FVector(1, -1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Right}},
|
||||
{FVector(-1, -1, -1), {EHyperTwistClassicCubeFace::Down, EHyperTwistClassicCubeFace::Back, EHyperTwistClassicCubeFace::Left}},
|
||||
};
|
||||
|
||||
for (const FPieceDef& Piece : Pieces)
|
||||
{
|
||||
CreatePiece(Piece.GridPos, Piece.Faces);
|
||||
}
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::CreatePiece(const FVector& GridPos, const TArray<EHyperTwistClassicCubeFace>& ColoredFaces)
|
||||
{
|
||||
UProceduralMeshComponent* Mesh = NewObject<UProceduralMeshComponent>(this, NAME_None, RF_Transactional);
|
||||
Mesh->RegisterComponent();
|
||||
Mesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
|
||||
PieceMeshes.Add(Mesh);
|
||||
|
||||
FVector Center = GridPos * (CubeletSize + Gap);
|
||||
float HalfSize = CubeletSize * 0.5f;
|
||||
|
||||
for (int32 i = 0; i < 6; ++i)
|
||||
{
|
||||
EHyperTwistClassicCubeFace Face = static_cast<EHyperTwistClassicCubeFace>(i);
|
||||
UMaterialInterface* Mat = ColoredFaces.Contains(Face) ? GetFaceMaterial(Face) : GetInternalMat();
|
||||
CreateCubeletFace(Mesh, i, Center, HalfSize, Face, Mat);
|
||||
}
|
||||
}
|
||||
|
||||
void AHyperTwistClassicCubeActor::CreateCubeletFace(UProceduralMeshComponent* Mesh, int32 SectionIndex,
|
||||
const FVector& Center, float HalfSize, EHyperTwistClassicCubeFace Face, UMaterialInterface* Material)
|
||||
{
|
||||
TArray<FVector> Vertices;
|
||||
TArray<int32> Triangles;
|
||||
TArray<FVector> Normals;
|
||||
TArray<FVector2D> UVs;
|
||||
TArray<FColor> Colors;
|
||||
TArray<FProcMeshTangent> Tangents;
|
||||
|
||||
FVector Normal;
|
||||
FVector TangentX;
|
||||
TArray<FVector> FaceVerts;
|
||||
|
||||
switch (Face)
|
||||
{
|
||||
case EHyperTwistClassicCubeFace::Up: // +Z
|
||||
Normal = FVector(0, 0, 1);
|
||||
TangentX = FVector(1, 0, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(-HalfSize, -HalfSize, +HalfSize),
|
||||
Center + FVector(+HalfSize, -HalfSize, +HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, +HalfSize),
|
||||
Center + FVector(-HalfSize, +HalfSize, +HalfSize)
|
||||
};
|
||||
break;
|
||||
|
||||
case EHyperTwistClassicCubeFace::Down: // -Z
|
||||
Normal = FVector(0, 0, -1);
|
||||
TangentX = FVector(-1, 0, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(+HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, +HalfSize, -HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, -HalfSize)
|
||||
};
|
||||
break;
|
||||
|
||||
case EHyperTwistClassicCubeFace::Front: // +Y
|
||||
Normal = FVector(0, 1, 0);
|
||||
TangentX = FVector(1, 0, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(-HalfSize, +HalfSize, -HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, -HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, +HalfSize),
|
||||
Center + FVector(-HalfSize, +HalfSize, +HalfSize)
|
||||
};
|
||||
break;
|
||||
|
||||
case EHyperTwistClassicCubeFace::Back: // -Y
|
||||
Normal = FVector(0, -1, 0);
|
||||
TangentX = FVector(-1, 0, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(+HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, -HalfSize, +HalfSize),
|
||||
Center + FVector(+HalfSize, -HalfSize, +HalfSize)
|
||||
};
|
||||
break;
|
||||
|
||||
case EHyperTwistClassicCubeFace::Right: // +X
|
||||
Normal = FVector(1, 0, 0);
|
||||
TangentX = FVector(0, 1, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(+HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, -HalfSize),
|
||||
Center + FVector(+HalfSize, +HalfSize, +HalfSize),
|
||||
Center + FVector(+HalfSize, -HalfSize, +HalfSize)
|
||||
};
|
||||
break;
|
||||
|
||||
case EHyperTwistClassicCubeFace::Left: // -X
|
||||
Normal = FVector(-1, 0, 0);
|
||||
TangentX = FVector(0, -1, 0);
|
||||
FaceVerts = {
|
||||
Center + FVector(-HalfSize, +HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, -HalfSize, -HalfSize),
|
||||
Center + FVector(-HalfSize, -HalfSize, +HalfSize),
|
||||
Center + FVector(-HalfSize, +HalfSize, +HalfSize)
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
Vertices = FaceVerts;
|
||||
Triangles = { 0, 1, 2, 0, 2, 3 };
|
||||
|
||||
for (int32 i = 0; i < 4; ++i)
|
||||
{
|
||||
Normals.Add(Normal);
|
||||
UVs.Add(FVector2D((i == 1 || i == 2) ? 1.0f : 0.0f, (i >= 2) ? 1.0f : 0.0f));
|
||||
Colors.Add(FColor::White);
|
||||
Tangents.Add(FProcMeshTangent(TangentX, false));
|
||||
}
|
||||
|
||||
Mesh->CreateMeshSection(SectionIndex, Vertices, Triangles, Normals, UVs, Colors, Tangents, true);
|
||||
if (Material)
|
||||
{
|
||||
Mesh->SetMaterial(SectionIndex, Material);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "HyperTwistSimulation/HyperTwistClassicCubeTypes.h"
|
||||
#include "ProceduralMeshComponent.h"
|
||||
#include "HyperTwistClassicCubeActor.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UNREALHYPERTWIST_API AHyperTwistClassicCubeActor : public AActor
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AHyperTwistClassicCubeActor();
|
||||
|
||||
/** Size of each cubelet (one small cube) in unreal units. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
float CubeletSize = 10.0f;
|
||||
|
||||
/** Gap between cubelets in unreal units. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
float Gap = 0.5f;
|
||||
|
||||
/** If true, generate cube geometry in OnConstruction (visible in editor). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
bool bGenerateOnConstruction = true;
|
||||
|
||||
/**
|
||||
* Override materials for each face.
|
||||
* Index order matches EHyperTwistClassicCubeFace: Up, Down, Front, Back, Left, Right.
|
||||
* If an entry is null, a default unlit color is generated at runtime.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
TArray<UMaterialInterface*> FaceMaterials;
|
||||
|
||||
/** Material for internal (non-visible) faces. If null, a dark gray default is used. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
UMaterialInterface* InternalMaterial;
|
||||
|
||||
virtual void OnConstruction(const FTransform& Transform) override;
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
private:
|
||||
void GenerateCube();
|
||||
void ClearPieces();
|
||||
void CreatePiece(const FVector& GridPos, const TArray<EHyperTwistClassicCubeFace>& ColoredFaces);
|
||||
void CreateCubeletFace(UProceduralMeshComponent* Mesh, int32 SectionIndex,
|
||||
const FVector& Center, float HalfSize, EHyperTwistClassicCubeFace Face,
|
||||
UMaterialInterface* Material);
|
||||
|
||||
UMaterialInterface* GetFaceMaterial(EHyperTwistClassicCubeFace Face);
|
||||
UMaterialInterface* GetInternalMat();
|
||||
void EnsureDefaultMaterials();
|
||||
|
||||
TArray<UProceduralMeshComponent*> PieceMeshes;
|
||||
TArray<UMaterialInterface*> DefaultFaceMats;
|
||||
UMaterialInterface* DefaultInternalMat = nullptr;
|
||||
bool bDefaultMaterialsCreated = false;
|
||||
};
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "HyperTwistClassicCubeTypes.generated.h"
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EHyperTwistClassicCubeFace : uint8
|
||||
{
|
||||
Up UMETA(DisplayName = "Up"),
|
||||
Down UMETA(DisplayName = "Down"),
|
||||
Front UMETA(DisplayName = "Front"),
|
||||
Back UMETA(DisplayName = "Back"),
|
||||
Left UMETA(DisplayName = "Left"),
|
||||
Right UMETA(DisplayName = "Right")
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FHyperTwistClassicCubePieceData
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
FVector GridPosition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "HyperTwist|Cube")
|
||||
TArray<EHyperTwistClassicCubeFace> ColoredFaces;
|
||||
};
|
||||
|
|
@ -9,7 +9,7 @@ public class UnrealHyperTwist : ModuleRules
|
|||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "Json", "JsonUtilities", "UMG", "Voice" });
|
||||
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "Json", "JsonUtilities", "UMG", "Voice", "ProceduralMeshComponent" });
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "HTTP" });
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@
|
|||
{
|
||||
"Name": "RemoteControl",
|
||||
"Enabled": true
|
||||
},
|
||||
{
|
||||
"Name": "ProceduralMeshComponent",
|
||||
"Enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -58,11 +58,11 @@ structural metadata.
|
|||
**Goal:** Enable actual donor code to be compiled, linked, and shipped.
|
||||
|
||||
**Deliverables:**
|
||||
- [ ] Create `.external/` directory with `CMakeLists.txt` wrapper for UE5 plugin-style builds
|
||||
- [ ] Create `ThirdParty/` directory for header-only and prebuilt libraries
|
||||
- [ ] Add `.gitmodules` for the first wave of C++ donor repos
|
||||
- [ ] Add `Build.cs` rules in `UnrealHyperTwist.Build.cs` for `PublicIncludePaths` and `PublicAdditionalLibraries`
|
||||
- [ ] Windows build validation after each sub-step (prove the linker sees donor symbols)
|
||||
- [x] Create `.external/` directory with 23 git submodules
|
||||
- [x] Create `ThirdParty/` directory for direct-source C++ integration
|
||||
- [x] Add `.gitmodules` for the first wave of C++ donor repos
|
||||
- [x] Add `Build.cs` rules in `UnrealHyperTwist.Build.cs` for `PublicIncludePaths`
|
||||
- [x] Windows build validation after each sub-step (prove the linker sees donor symbols)
|
||||
|
||||
**Estimated actions:** ~15 build actions per sub-step
|
||||
**Estimated time:** 2–3 hours per sub-step (infrastructure compiles fast)
|
||||
|
|
@ -75,11 +75,14 @@ structural metadata.
|
|||
See `HYPERTWIST_UNWIRED_REPO_INVENTORY_AND_WIRING_SCHEDULE_2026-06-10.md`
|
||||
for the full 29-repo queue and per-repo wiring posture.
|
||||
|
||||
### 1A — Solver Backend: `efrantar/rob-twophase`
|
||||
- [ ] Add submodule `mirrors/rob-twophase`
|
||||
- [ ] Write UE `Build.cs` rules linking `libtwophase` or object files
|
||||
- [ ] Expose `UHyperTwistSolverLibrary::SolveClassicState(FString KociembaState)` → `TArray<FString> MoveSequence`
|
||||
- [ ] Automation test: feed a known scrambled state, assert solution length < 25
|
||||
### 1A — Solver Backend: `efrantar/rob-twophase` ✅ COMPLETE
|
||||
- [x] Add submodule `mirrors/rob-twophase`
|
||||
- [x] Copy source to `Private/ThirdParty/rob-twophase/`
|
||||
- [x] Fix UE macro conflicts (`check`→`ValidateCube`, `UF`→`UF_EDGE`)
|
||||
- [x] Add `msvc_compat.h` for POSIX `ffs`/`ffsll` on Windows
|
||||
- [x] Fix `unistd.h` → `direct.h`/`io.h`, `qt_skip1` C4700
|
||||
- [x] Windows build validated: 5 actions, 38.87s, exit code 0
|
||||
- [ ] Runtime test: feed a known scrambled state, assert solution length < 25 (deferred to Phase 4C)
|
||||
|
||||
### 1B — Speech-to-Text: `freestyle-voice/freestyle` (MIT)
|
||||
- [ ] Decision gate: `freestyle` is a hotkey-driven dictation client, not an embeddable C++ library. It calls cloud APIs (OpenAI, Groq, Anthropic, Google, Deepgram, ElevenLabs) via HTTP.
|
||||
|
|
@ -411,7 +414,10 @@ for the full 29-repo queue and per-repo wiring posture.
|
|||
|
||||
## Immediate Next Step
|
||||
|
||||
**Phase 0A:** Create `.external/` and `ThirdParty/`, add `.gitmodules` for
|
||||
`freestyle-voice/freestyle` as the proof-of-concept speech integration.
|
||||
**Phase 2A:** Procedural Classic Cube Geometry. Create `AHyperTwistClassicCubeActor`
|
||||
with 26 `UProceduralMeshComponent` pieces (6 centers, 12 edges, 8 corners) arranged
|
||||
in a 3×3×3 grid with per-face colored materials. This is the highest-priority
|
||||
functional gap — it blocks every user-facing feature.
|
||||
|
||||
This is the smallest step that proves the repo-wiring infrastructure works.
|
||||
Solver backend (Phase 1A) is compiled and linked. It will be exercised once
|
||||
the renderer exists (Phase 4: hint/solve integration).
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue