hack up main to test hittesting
diff --git a/skia/viewer/src/main.cpp b/skia/viewer/src/main.cpp
index a64d569..2023a41 100644
--- a/skia/viewer/src/main.cpp
+++ b/skia/viewer/src/main.cpp
@@ -22,6 +22,7 @@
 #include "rive/artboard.hpp"
 #include "rive/file.hpp"
 #include "rive/layout.hpp"
+#include "rive/nested_artboard.hpp"
 #include "rive/math/aabb.hpp"
 #include "skia_renderer.hpp"
 
@@ -32,6 +33,9 @@
 #include <stdio.h>
 
 std::string filename;
+const char* artboardName = "Bullet Man";
+const char* animationName;
+
 rive::File* currentFile = nullptr;
 rive::Artboard* artboard = nullptr;
 rive::StateMachineInstance* stateMachineInstance = nullptr;
@@ -54,7 +58,10 @@
         fprintf(stderr, "failed to import file\n");
         return;
     }
-    auto sourceArtboard = file->artboard();
+    auto sourceArtboard = file->artboard(artboardName);
+    if (!sourceArtboard) {
+        sourceArtboard = file->artboard();
+    }
     // Artboard should always be instance and hence must be deleted.
     delete artboard;
     artboard = sourceArtboard->instance();
@@ -76,6 +83,41 @@
     currentFile = file;
 }
 
+static void dump_inputs(rive::StateMachine* machine) {
+    std::unique_ptr<rive::StateMachineInstance> inst(new rive::StateMachineInstance(machine));
+
+    printf("state machine: %s needs advance %d\n",
+           machine->name().c_str(), inst->needsAdvance());
+
+    for (size_t i = 0; i < inst->inputCount(); ++i) {
+        rive::SMIInput* input = inst->input(i);
+        auto input_inst = input->input();
+        const char* name = input_inst->name().c_str();
+        if (input_inst->is<rive::StateMachineNumber>()) {
+            printf("   number: %s\n", name);
+        }
+        else if (input_inst->is<rive::StateMachineBool>()) {
+            printf("     bool: %s\n", name);
+        }
+        else if (input_inst->is<rive::StateMachineTrigger>()) {
+            printf("  trigger: %s\n", name);
+        }
+    }
+}
+
+static void dump_machines(rive::Artboard* artboard) {
+    for (size_t i = 0; i < artboard->stateMachineCount(); ++i) {
+        auto machine = artboard->stateMachine(i);
+        dump_inputs(machine);
+    }
+}
+
+static void fire(rive::StateMachineInstance* smi, const char trigger[]) {
+    auto tr = smi->getTrigger(trigger);
+    assert(tr);
+    tr->fire();
+}
+
 void initAnimation(int index) {
     animationIndex = index;
     stateMachineIndex = -1;
@@ -88,7 +130,12 @@
         fprintf(stderr, "failed to import file\n");
         return;
     }
-    auto sourceArtboard = file->artboard();
+    auto sourceArtboard = file->artboard(artboardName);
+    if (!sourceArtboard) {
+        sourceArtboard = file->artboard();
+    }
+    dump_machines(sourceArtboard);
+
     // Artboard should always be instance and hence must be deleted.
     delete artboard;
     artboard = sourceArtboard->instance();
@@ -108,6 +155,8 @@
     }
 
     currentFile = file;
+    
+    initStateMachine(0);
 }
 
 void glfwErrorCallback(int error, const char* description) {
@@ -116,6 +165,7 @@
 
 void glfwDropCallback(GLFWwindow* window, int count, const char** paths) {
     // Just get the last dropped file for now...
+    printf("dropcallback %d %s\n", count, paths[count-1]);
     filename = paths[count - 1];
 
     FILE* fp = fopen(filename.c_str(), "r");
@@ -132,7 +182,90 @@
     initAnimation(0);
 }
 
-int main() {
+static bool handle_click(rive::Artboard* artboard, const char name[]) {
+    const struct {
+        const char* click;
+        const char* machine;
+        const char* trigger;
+    } triggers[] = {
+        { "hand-wick",   "State Machine 1", "Light", },
+        { "hand-fire",   "State Machine 1", "Cannon", },
+        { "hand-helmet", "State Machine 1", "Helmet", },
+    };
+    
+    for (const auto& t : triggers) {
+        if (strcmp(name, t.click) == 0) {
+            printf("found\n");
+            fire(stateMachineInstance, t.trigger);
+            return true;
+        }
+    }
+    return false;
+}
+
+static void test_hittest(rive::Artboard* artboard, const SkMatrix& ctm) {
+    const auto mouse = ImGui::GetMousePos();
+
+    SkMatrix inv;
+    (void)ctm.invert(&inv);
+    auto pt = inv.mapXY(mouse.x * 2, mouse.y * 2);
+    
+    const auto bounds = artboard->bounds();
+    if (pt.x() < bounds.left() || pt.x() >= bounds.right() ||
+        pt.y() < bounds.top() || pt.y() >= bounds.bottom()) {
+        return;
+    }
+    
+    rive::HitInfo hinfo;
+    hinfo.area = rive::AABB(pt.fX - 1, pt.fY - 1, pt.fX + 2, pt.fY + 2).round();
+
+    static rive::Core* gPrev;
+
+    auto node = artboard->hitTest(&hinfo);
+    if (node != gPrev) {
+        gPrev = node;
+        const char* name = nullptr;
+        if (node) {
+            assert(node->is<rive::Component>());
+
+            name = node->as<rive::Component>()->name().c_str();
+            printf("(%s) mounts [ ", name);
+            for (auto na : hinfo.mounts) {
+                const char* naname = nullptr;
+                if (na) {
+                    naname = na->name().c_str();
+                }
+                printf("(%s) ", naname);
+            }
+            printf("]\n");
+            
+            if (hinfo.mounts.size() == 1) {
+                handle_click(artboard, hinfo.mounts[0]->name().c_str());
+            }
+        } else {
+            printf("no hit\n");
+        }
+    }
+}
+
+int main(int argc, const char* argv[]) {
+    for (int i = 1; i < argc; ++i) {
+        if (strcmp(argv[i], "--file") == 0) {
+            filename = argv[++i];
+            printf("file %s\n", filename.c_str());
+            continue;
+        }
+        if (strcmp(argv[i], "--artboard") == 0) {
+            artboardName = argv[++i];
+            printf("artb %s\n", artboardName);
+            continue;
+        }
+        if (strcmp(argv[i], "--animation") == 0) {
+            animationName = argv[++i];
+            continue;
+        }
+    }
+
     if (!glfwInit()) {
         fprintf(stderr, "Failed to initialize glfw.\n");
         return 1;
@@ -250,8 +383,12 @@
                            rive::Alignment::center,
                            rive::AABB(0, 0, width, height),
                            artboard->bounds());
+            auto mx = canvas->getTotalMatrix();
+
             artboard->draw(&renderer);
             renderer.restore();
+            
+            test_hittest(artboard, mx);
         }
 
         context->flush();
@@ -373,4 +510,4 @@
     glfwTerminate();
 
     return 0;
-}
\ No newline at end of file
+}