X-Git-Url: https://git.lukelau.me/?p=opengl.git;a=blobdiff_plain;f=ui.mm;h=26be31d5c05eb41fee3c19e34c000e3d0f532445;hp=c2a0c6f50ace0e0b495d7b0a1c6c8a6c5315089c;hb=9886c33eb8cd31f28234585718410cd51aef2a4c;hpb=d2a4cfcd292f5bc422a025d43855e5f4f21fb161 diff --git a/ui.mm b/ui.mm index c2a0c6f..26be31d 100644 --- a/ui.mm +++ b/ui.mm @@ -1,50 +1,142 @@ +#import "ui.hpp" #import -#import "ui.h" @interface Controller : NSObject -- (instancetype)initWithCallback:(void(*)(int, float))callback; +- (instancetype)initWithBlendshapeNames:(NSArray *)names + delegate:(ControlWindowDelegate *)delegate; - (void)sliderMoved:(id)sender; - +@property(readonly) NSView *view; @end @implementation Controller { - void (*weightChanged)(int, float); + size_t numBlendshapes; + ControlWindowDelegate *delegate; + NSMutableArray *sliders; } -- (instancetype)initWithCallback:(void(*)(int, float))callback { +- (instancetype)initWithBlendshapeNames:(NSArray *)names + delegate:(ControlWindowDelegate *)d { if (self = [super init]) { - self->weightChanged = callback; + self->numBlendshapes = [names count]; + self->delegate = d; } + + sliders = [NSMutableArray arrayWithCapacity:numBlendshapes]; + NSStackView *stackView = [NSStackView stackViewWithViews:sliders]; + + for (int i = 0; i < numBlendshapes; i++) { + NSSlider *slider = [NSSlider sliderWithTarget:self + action:@selector(sliderMoved:)]; + [slider setTag:i]; + sliders[i] = slider; + + NSTextField *label = [NSTextField labelWithString:names[i]]; + NSStackView *rowStackView = + [NSStackView stackViewWithViews:@[ label, slider ]]; + [stackView addView:rowStackView inGravity:NSStackViewGravityTop]; + } + + NSButton *solveButton = [NSButton buttonWithTitle:@"Solve weights" + target:self + action:@selector(solveWeights:)]; + NSButton *resetButton = [NSButton buttonWithTitle:@"Reset weights" + target:self + action:@selector(resetWeights:)]; + NSStackView *buttonStack = + [NSStackView stackViewWithViews:@[ solveButton, resetButton ]]; + [stackView addView:buttonStack inGravity:NSStackViewGravityTop]; + + NSButton *manipsButton = + [NSButton buttonWithTitle:@"Reset Manipulators" + target:self + action:@selector(resetManipulators:)]; + [stackView addView:manipsButton inGravity:NSStackViewGravityTop]; + + NSButton *animCheckbox = + [NSButton checkboxWithTitle:@"Play animation" + target:self + action:@selector(animationPlayback:)]; + [stackView addView:animCheckbox inGravity:NSStackViewGravityTop]; + + [stackView setOrientation:NSUserInterfaceLayoutOrientationVertical]; + [stackView setEdgeInsets:NSEdgeInsetsMake(16, 16, 16, 16)]; + _view = stackView; + return self; } - (void)sliderMoved:(id)sender { NSSlider *slider = (NSSlider *)sender; - weightChanged([slider tag], [slider floatValue]); + delegate->weightChanged([slider tag], [slider floatValue]); +} + +- (void)solveWeights:(id)sender { + std::vector newWeights(numBlendshapes); + delegate->solveWeights(newWeights); + for (int i = 0; i < numBlendshapes; i++) + [sliders[i] setFloatValue:newWeights[i]]; } + +- (void)resetWeights:(id)sender { + for (int i = 0; i < numBlendshapes; i++) { + [sliders[i] setFloatValue:0]; + delegate->weightChanged(i, 0); + } +} + +- (void)resetManipulators:(id)sender { + delegate->resetManipulators(); +} + +- (void)animationPlayback:(id)sender { + bool play = [(NSButton *)sender state] == NSControlStateValueOn; + for (int i = 0; i < [sliders count]; i++) + [sliders[i] setEnabled: !play]; + delegate->playbackChanged(play); +} + +- (void)updateWeights:(NSArray *)newWeights { + for (int i = 0; i < [newWeights count]; i++) + [sliders[i] setFloatValue:[newWeights[i] floatValue]]; +} + @end -void createControlWindow(size_t numBlendshapes, const char **names, void(*weightChanged)(int, float)) { - Controller *controller = [[Controller alloc] initWithCallback: weightChanged]; +ControlWindow createControlWindow(std::vector names, + ControlWindowDelegate *delegate) { + NSMutableArray *nsNames = + [NSMutableArray arrayWithCapacity:names.size()]; + for (auto &n : names) + [nsNames addObject:[NSString stringWithUTF8String:n.c_str()]]; + Controller *controller = + [[Controller alloc] initWithBlendshapeNames:(NSArray *)nsNames + delegate:delegate]; - NSWindowStyleMask mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskUtilityWindow; - NSWindow *window = [[NSPanel alloc] initWithContentRect: NSMakeRect(20, 20, 340, 420) - styleMask:mask backing:NSBackingStoreBuffered defer:NO]; + NSWindowStyleMask mask = NSWindowStyleMaskTitled | + NSWindowStyleMaskClosable | + NSWindowStyleMaskUtilityWindow; + NSWindow *window = + [[NSPanel alloc] initWithContentRect:NSMakeRect(20, 20, 340, 420) + styleMask:mask + backing:NSBackingStoreBuffered + defer:NO]; [window makeKeyAndOrderFront:nil]; [window setTitle:@"Blendshapes"]; + [window setContentView:[controller view]]; - NSMutableArray *sliders = [NSMutableArray arrayWithCapacity: numBlendshapes]; + return {window, controller}; +} - for (int i = 0; i < numBlendshapes; i++) { - NSSlider *slider = [NSSlider sliderWithTarget: controller action:@selector(sliderMoved:)]; - [slider setTag: i]; - NSTextField *label = [NSTextField labelWithString: [NSString stringWithUTF8String: names[i]]]; - NSStackView *stackView = [NSStackView stackViewWithViews: @[label, slider]]; - sliders[i] = stackView; +bool isPanelFocused(ControlWindow cw) { + NSWindow *win = (NSWindow *)cw.window; + return [win isKeyWindow]; } - NSStackView *stackView = [NSStackView stackViewWithViews: sliders]; - [stackView setOrientation: NSUserInterfaceLayoutOrientationVertical]; - [stackView setEdgeInsets: NSEdgeInsetsMake(16, 16, 16, 16)]; - [window setContentView: stackView]; +void updateWeights(ControlWindow *cw, std::vector weights) { + Controller *c = (Controller *)cw->controller; + NSMutableArray *nsWeights = + [NSMutableArray arrayWithCapacity:weights.size()]; + for (int i = 0; i < weights.size(); i++) + nsWeights[i] = [NSNumber numberWithFloat:weights[i]]; + [c updateWeights:(NSArray *)nsWeights]; }