diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 8a1306a..0fdb0f8 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -3523,4 +3523,13 @@ target_link_libraries(step515_test PRIVATE tree_sitter_javascript tree_sitter_typescript tree_sitter_java tree_sitter_rust tree_sitter_go) +add_executable(step516_test tests/step516_test.cpp) +target_include_directories(step516_test PRIVATE src) +target_link_libraries(step516_test PRIVATE + nlohmann_json::nlohmann_json + unofficial::tree-sitter::tree-sitter + tree_sitter_python tree_sitter_cpp tree_sitter_elisp + tree_sitter_javascript tree_sitter_typescript + tree_sitter_java tree_sitter_rust tree_sitter_go) + # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) diff --git a/editor/src/SignatureVisualIdentity.h b/editor/src/SignatureVisualIdentity.h new file mode 100644 index 0000000..f603bea --- /dev/null +++ b/editor/src/SignatureVisualIdentity.h @@ -0,0 +1,81 @@ +#pragma once +// Step 516: Signature Visual Identity Pack +// Encodes black-surface gradient treatment, blade-edge accents, and +// electric-blue logic link styling. + +#include +#include +#include + +struct GradientStop { + float t = 0.0f; + float r = 0.0f; + float g = 0.0f; + float b = 0.0f; + float a = 1.0f; +}; + +struct EdgeAccent { + std::string edge; // left/right/top/bottom + float thickness = 1.0f; + float intensity = 0.0f; + bool active = false; +}; + +struct LogicLinkStyle { + float width = 1.0f; + float glow = 0.0f; + float r = 0.15f; + float g = 0.56f; + float b = 0.95f; + float alpha = 1.0f; +}; + +class SignatureVisualIdentity { +public: + static std::vector blackSurfaceGradient(bool elevated) { + if (elevated) { + return { + {0.0f, 0.02f, 0.02f, 0.02f, 1.0f}, + {0.45f, 0.08f, 0.08f, 0.08f, 1.0f}, + {1.0f, 0.14f, 0.14f, 0.14f, 1.0f} + }; + } + return { + {0.0f, 0.01f, 0.01f, 0.01f, 1.0f}, + {0.60f, 0.05f, 0.05f, 0.05f, 1.0f}, + {1.0f, 0.09f, 0.09f, 0.09f, 1.0f} + }; + } + + static EdgeAccent bladeEdge(const std::string& edge, bool active, float emphasis) { + EdgeAccent a; + a.edge = edge; + a.active = active; + a.thickness = active ? 2.0f : 1.0f; + a.intensity = active ? std::max(0.2f, std::min(1.0f, emphasis)) : 0.12f; + return a; + } + + static LogicLinkStyle electricBlueLink(bool highlighted, float distanceNorm) { + LogicLinkStyle s; + s.width = highlighted ? 2.4f : 1.4f; + s.glow = highlighted ? 0.80f : 0.35f; + float fade = std::max(0.35f, 1.0f - std::max(0.0f, std::min(1.0f, distanceNorm)) * 0.45f); + s.alpha = fade; + return s; + } + + static bool isElectricBlue(const LogicLinkStyle& s) { + return s.b > s.r && s.b > s.g && s.g > s.r; + } + + static float revealDurationMs(bool reducedMotion) { + return reducedMotion ? 80.0f : 220.0f; + } + + static float staggerDelayMs(int index, bool reducedMotion) { + if (reducedMotion) return 0.0f; + return std::max(0, index) * 24.0f; + } +}; diff --git a/editor/tests/step516_test.cpp b/editor/tests/step516_test.cpp new file mode 100644 index 0000000..4228043 --- /dev/null +++ b/editor/tests/step516_test.cpp @@ -0,0 +1,123 @@ +// Step 516: Signature Visual Identity Pack (12 tests) + +#include "SignatureVisualIdentity.h" + +#include + +static int passed = 0, failed = 0; +#define TEST(name) { std::cout << " " << #name << "... "; } +#define PASS() { std::cout << "PASS\n"; ++passed; } +#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; } +#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {} + +void test_gradient_has_three_stops() { + TEST(gradient_has_three_stops); + auto g = SignatureVisualIdentity::blackSurfaceGradient(false); + CHECK(g.size() == 3, "expected 3 stops"); + PASS(); +} + +void test_elevated_gradient_brighter_than_base() { + TEST(elevated_gradient_brighter_than_base); + auto a = SignatureVisualIdentity::blackSurfaceGradient(false); + auto b = SignatureVisualIdentity::blackSurfaceGradient(true); + CHECK(b.back().r > a.back().r, "elevated gradient should be brighter"); + PASS(); +} + +void test_blade_edge_active_increases_thickness() { + TEST(blade_edge_active_increases_thickness); + auto idle = SignatureVisualIdentity::bladeEdge("left", false, 0.5f); + auto active = SignatureVisualIdentity::bladeEdge("left", true, 0.5f); + CHECK(active.thickness > idle.thickness, "active edge should be thicker"); + PASS(); +} + +void test_blade_edge_active_uses_higher_intensity() { + TEST(blade_edge_active_uses_higher_intensity); + auto idle = SignatureVisualIdentity::bladeEdge("left", false, 0.5f); + auto active = SignatureVisualIdentity::bladeEdge("left", true, 0.7f); + CHECK(active.intensity > idle.intensity, "active edge should be stronger"); + PASS(); +} + +void test_logic_link_highlight_increases_width() { + TEST(logic_link_highlight_increases_width); + auto normal = SignatureVisualIdentity::electricBlueLink(false, 0.1f); + auto hi = SignatureVisualIdentity::electricBlueLink(true, 0.1f); + CHECK(hi.width > normal.width, "highlight should increase width"); + PASS(); +} + +void test_logic_link_highlight_increases_glow() { + TEST(logic_link_highlight_increases_glow); + auto normal = SignatureVisualIdentity::electricBlueLink(false, 0.1f); + auto hi = SignatureVisualIdentity::electricBlueLink(true, 0.1f); + CHECK(hi.glow > normal.glow, "highlight should increase glow"); + PASS(); +} + +void test_logic_link_alpha_fades_with_distance() { + TEST(logic_link_alpha_fades_with_distance); + auto near = SignatureVisualIdentity::electricBlueLink(false, 0.0f); + auto far = SignatureVisualIdentity::electricBlueLink(false, 1.0f); + CHECK(near.alpha > far.alpha, "alpha should fade with distance"); + PASS(); +} + +void test_logic_link_is_electric_blue() { + TEST(logic_link_is_electric_blue); + auto s = SignatureVisualIdentity::electricBlueLink(true, 0.3f); + CHECK(SignatureVisualIdentity::isElectricBlue(s), "expected electric-blue profile"); + PASS(); +} + +void test_reveal_duration_shorter_in_reduced_motion() { + TEST(reveal_duration_shorter_in_reduced_motion); + auto normal = SignatureVisualIdentity::revealDurationMs(false); + auto reduced = SignatureVisualIdentity::revealDurationMs(true); + CHECK(reduced < normal, "reduced-motion reveal should be shorter"); + PASS(); +} + +void test_stagger_delay_zero_in_reduced_motion() { + TEST(stagger_delay_zero_in_reduced_motion); + CHECK(SignatureVisualIdentity::staggerDelayMs(3, true) == 0.0f, + "reduced-motion stagger should be zero"); + PASS(); +} + +void test_stagger_delay_grows_with_index() { + TEST(stagger_delay_grows_with_index); + auto a = SignatureVisualIdentity::staggerDelayMs(1, false); + auto b = SignatureVisualIdentity::staggerDelayMs(4, false); + CHECK(b > a, "stagger should increase with index"); + PASS(); +} + +void test_gradient_t_values_are_ordered() { + TEST(gradient_t_values_are_ordered); + auto g = SignatureVisualIdentity::blackSurfaceGradient(true); + CHECK(g[0].t < g[1].t && g[1].t < g[2].t, "gradient t-values must be ordered"); + PASS(); +} + +int main() { + std::cout << "Step 516: Signature Visual Identity Pack\n"; + + test_gradient_has_three_stops(); // 1 + test_elevated_gradient_brighter_than_base(); // 2 + test_blade_edge_active_increases_thickness(); // 3 + test_blade_edge_active_uses_higher_intensity(); // 4 + test_logic_link_highlight_increases_width(); // 5 + test_logic_link_highlight_increases_glow(); // 6 + test_logic_link_alpha_fades_with_distance(); // 7 + test_logic_link_is_electric_blue(); // 8 + test_reveal_duration_shorter_in_reduced_motion(); // 9 + test_stagger_delay_zero_in_reduced_motion(); // 10 + test_stagger_delay_grows_with_index(); // 11 + test_gradient_t_values_are_ordered(); // 12 + + std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n"; + return failed == 0 ? 0 : 1; +} diff --git a/progress.md b/progress.md index 225b74a..7d4a16a 100644 --- a/progress.md +++ b/progress.md @@ -8247,3 +8247,39 @@ scales, derivation support, and AA contrast validation. - `editor/src/ThemeTokenSystemV2.h` within header-size limit (`107` <= `600`) - `editor/tests/step515_test.cpp` within test-file size guidance (`121` lines) - Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md` + +### Step 516: Signature Visual Identity Pack +**Status:** PASS (12/12 tests) + +Implements Sprint 26’s signature visual identity primitives: black-surface +gradient depth treatment, blade-edge accent semantics for active surfaces, and +electric-blue logic-link styling with distance-aware fading and motion-aware +reveal timing. + +**Files added:** +- `editor/src/SignatureVisualIdentity.h` - visual identity module: + - elevated/base black-surface gradient presets + - blade-edge accent model (edge, thickness, intensity, active state) + - electric-blue logic-link style with highlight and distance fade behavior + - reduced-motion aware reveal and stagger timing helpers +- `editor/tests/step516_test.cpp` - 12 tests covering: + - gradient stop structure/order and elevated-depth brightness + - active blade-edge thickness/intensity behavior + - highlighted link width/glow behavior + - distance-based logic-link alpha fade + - electric-blue profile detection + - reduced-motion reveal/stagger behavior + +**Files modified:** +- `editor/CMakeLists.txt` - `step516_test` target + +**Verification run:** +- `cmake -S editor -B editor/build-native` - PASS +- `cmake --build editor/build-native --target step516_test` - PASS +- `./editor/build-native/step516_test` - PASS (12/12) +- `./editor/build-native/step515_test` - PASS (12/12) regression coverage + +**Architecture gate check:** +- `editor/src/SignatureVisualIdentity.h` within header-size limit (`81` <= `600`) +- `editor/tests/step516_test.cpp` within test-file size guidance (`123` lines) +- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`