2 #import <Cocoa/Cocoa.h>
4 @interface Controller : NSObject
5 - (instancetype)initWithBlendshapeNames:(NSArray<NSString *> *)names
6 delegate:(ControlWindowDelegate *)delegate;
7 - (void)sliderMoved:(id)sender;
8 @property(readonly) NSView *view;
11 @implementation Controller {
12 size_t numBlendshapes;
13 ControlWindowDelegate *delegate;
14 NSMutableArray<NSControl *> *sliders;
17 - (instancetype)initWithBlendshapeNames:(NSArray<NSString *> *)names
18 delegate:(ControlWindowDelegate *)d {
19 if (self = [super init]) {
20 self->numBlendshapes = [names count];
24 sliders = [NSMutableArray arrayWithCapacity:numBlendshapes];
25 NSStackView *stackView = [NSStackView stackViewWithViews:sliders];
27 for (int i = 0; i < numBlendshapes; i++) {
28 NSSlider *slider = [NSSlider sliderWithTarget:self
29 action:@selector(sliderMoved:)];
33 NSTextField *label = [NSTextField labelWithString:names[i]];
34 NSStackView *rowStackView =
35 [NSStackView stackViewWithViews:@[ label, slider ]];
36 [stackView addView:rowStackView inGravity:NSStackViewGravityTop];
39 NSButton *solveButton = [NSButton buttonWithTitle:@"Solve weights"
41 action:@selector(solveWeights:)];
42 NSButton *resetButton = [NSButton buttonWithTitle:@"Reset weights"
44 action:@selector(resetWeights:)];
45 NSStackView *buttonStack =
46 [NSStackView stackViewWithViews:@[ solveButton, resetButton ]];
47 [stackView addView:buttonStack inGravity:NSStackViewGravityTop];
49 NSButton *manipsButton =
50 [NSButton buttonWithTitle:@"Reset Manipulators"
52 action:@selector(resetManipulators:)];
53 [stackView addView:manipsButton inGravity:NSStackViewGravityTop];
55 NSButton *animCheckbox =
56 [NSButton checkboxWithTitle:@"Play animation"
58 action:@selector(animationPlayback:)];
59 [stackView addView:animCheckbox inGravity:NSStackViewGravityTop];
61 [stackView setOrientation:NSUserInterfaceLayoutOrientationVertical];
62 [stackView setEdgeInsets:NSEdgeInsetsMake(16, 16, 16, 16)];
68 - (void)sliderMoved:(id)sender {
69 NSSlider *slider = (NSSlider *)sender;
70 delegate->weightChanged([slider tag], [slider floatValue]);
73 - (void)solveWeights:(id)sender {
74 std::vector<float> newWeights(numBlendshapes);
75 delegate->solveWeights(newWeights);
76 for (int i = 0; i < numBlendshapes; i++)
77 [sliders[i] setFloatValue:newWeights[i]];
80 - (void)resetWeights:(id)sender {
81 for (int i = 0; i < numBlendshapes; i++) {
82 [sliders[i] setFloatValue:0];
83 delegate->weightChanged(i, 0);
87 - (void)resetManipulators:(id)sender {
88 delegate->resetManipulators();
91 - (void)animationPlayback:(id)sender {
92 bool play = [(NSButton *)sender state] == NSControlStateValueOn;
93 for (int i = 0; i < [sliders count]; i++)
94 [sliders[i] setEnabled: !play];
95 delegate->playbackChanged(play);
98 - (void)updateWeights:(NSArray<NSNumber *> *)newWeights {
99 for (int i = 0; i < [newWeights count]; i++)
100 [sliders[i] setFloatValue:[newWeights[i] floatValue]];
105 ControlWindow createControlWindow(std::vector<std::string> names,
106 ControlWindowDelegate *delegate) {
107 NSMutableArray<NSString *> *nsNames =
108 [NSMutableArray arrayWithCapacity:names.size()];
109 for (auto &n : names)
110 [nsNames addObject:[NSString stringWithUTF8String:n.c_str()]];
111 Controller *controller =
112 [[Controller alloc] initWithBlendshapeNames:(NSArray *)nsNames
115 NSWindowStyleMask mask = NSWindowStyleMaskTitled |
116 NSWindowStyleMaskClosable |
117 NSWindowStyleMaskUtilityWindow;
119 [[NSPanel alloc] initWithContentRect:NSMakeRect(20, 20, 340, 420)
121 backing:NSBackingStoreBuffered
123 [window makeKeyAndOrderFront:nil];
124 [window setTitle:@"Blendshapes"];
125 [window setContentView:[controller view]];
127 return {window, controller};
130 bool isPanelFocused(ControlWindow cw) {
131 NSWindow *win = (NSWindow *)cw.window;
132 return [win isKeyWindow];
135 void updateWeights(ControlWindow *cw, std::vector<float> weights) {
136 Controller *c = (Controller *)cw->controller;
137 NSMutableArray<NSNumber *> *nsWeights =
138 [NSMutableArray arrayWithCapacity:weights.size()];
139 for (int i = 0; i < weights.size(); i++)
140 nsWeights[i] = [NSNumber numberWithFloat:weights[i]];
141 [c updateWeights:(NSArray *)nsWeights];