Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: samplecode/SampleBevel.cpp

Issue 2259183003: Added a small widget framework to the interactive bevel SampleApp (Closed) Base URL: https://skia.googlesource.com/skia@bevel-interactive
Patch Set: Made control constructors private Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SampleCode.h" 8 #include "SampleCode.h"
9 #include "SkCanvas.h" 9 #include "SkCanvas.h"
10 #include "SkLightingShader.h" 10 #include "SkLightingShader.h"
11 #include "SkNormalSource.h" 11 #include "SkNormalSource.h"
12 #include "sk_tool_utils.h" 12 #include "sk_tool_utils.h"
13 13
14 class ParentControl;
15
16 // Abstract base class for all components that a control panel must have
17 class Control : public SkRefCnt {
18 public:
robertphillips 2016/08/19 17:50:20 one line ?
dvonbeck 2016/08/19 18:25:17 Done.
19 Control(SkString name)
20 : fName(name), fParent(nullptr), fRelativeY(0) {}
21
22 // Use this to propagate a click's position down to a control. Gets modulate d by the component's
23 // relative position
robertphillips 2016/08/19 17:50:19 const & ?
dvonbeck 2016/08/19 18:25:16 Done.
24 bool click(SkPoint clickPos) {
25 SkPoint relativeClickPos = SkPoint::Make(clickPos.fX, clickPos.fY - fRel ativeY);
26 return this->onClick(relativeClickPos);
27 }
28
29 // Use this to draw the control and its appropriate children. Gets modulated by the component's
30 // relative position.
31 void drawContent(SkCanvas *canvas) {
32 canvas->save();
33 canvas->translate(0, fRelativeY);
34 this->onDrawContent(canvas);
35 canvas->restore();
36 }
37
robertphillips 2016/08/19 17:50:19 argumend ?
dvonbeck 2016/08/19 18:25:17 Done.
38 // Returns true when click position argumend lands over a control region in this control. Click
39 // position gets modulated by the component's relative position.
robertphillips 2016/08/19 17:50:19 const& ?
dvonbeck 2016/08/19 18:25:18 Done.
40 bool isInCtrlRegion(SkPoint click) {
41 SkPoint relativeClickPos = SkPoint::Make(click.fX, click.fY - fRelativeY );
42 return this->onIsInCtrlRegion(relativeClickPos);
43 }
44
45 // Returns height of content drawn
46 virtual SkScalar height() const = 0;
47
48 // Sets the parent of this component. May only be used once. Height must rem ain constant after
49 // parent is set.
50 void setParent(ParentControl *parent, SkScalar relativeY) {
51 SkASSERT(parent);
52 SkASSERT(!fParent); // No chidren transfer since relativeY would get inv alid for younger kid
53
54 fParent = parent;
55 fRelativeY = relativeY;
56 this->onSetParent();
57 }
58
59 // Overriden by sub-classes that need to recompute fields after parent is se t. Called after
60 // setting fParent.
61 virtual void onSetParent() {}
62
63 // Overriden by sub-classes that need to know when a click is released.
64 virtual void onClickRelease() {}
65
66 protected:
67
68 // Draws a label for the component, using its name and a passed value. Does NOT modulate by
69 // relative height, expects CTM to have been adjusted in advance.
robertphillips 2016/08/19 17:50:19 & on string ?
dvonbeck 2016/08/19 18:25:18 Done.
70 void drawLabel(SkCanvas *canvas, const SkString valueStr) const {
71 // TODO Cache this
72 sk_sp<SkTypeface> fLabelTypeface =
73 sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyl e());
74
75 SkString label;
76 label.append(fName);
77 label.append(": ");
78 label.append(valueStr);
79
80 SkPaint labelPaint;
81 labelPaint.setTypeface(fLabelTypeface);
82 labelPaint.setAntiAlias(true);
83 labelPaint.setColor(0xFFFFFFFF);
84 labelPaint.setTextSize(12.0f);
85
86 canvas->drawText(label.c_str(), label.size(), 0, kLabelHeight - 6.0f, la belPaint);
87 }
88
89 SkString fName;
90 ParentControl* fParent;
91
92 static constexpr SkScalar kLabelHeight = 20.0f;
93
94 private:
95 // Overriden by sub-class to draw component. Do not call directly, drawConte nt() modulates by
96 // relative position.
97 virtual void onDrawContent(SkCanvas *canvas) = 0;
98
99 // Overriden by sub-class to handle clicks. Do not call directly, click() mo dulates by relative
100 // position. Return true if holding mouse capture
101 virtual bool onClick(SkPoint clickPos) { return false; };
egdaniel 2016/08/19 17:56:35 const &
dvonbeck 2016/08/19 18:25:18 Done.
102
103 // Overriden by sub-classes with controls. Should return true if clickPos la nds inside a control
104 // region, to enable mouse caputre.
robertphillips 2016/08/19 17:50:19 const SkPoint& ?
dvonbeck 2016/08/19 18:25:17 Done.
105 virtual bool onIsInCtrlRegion(SkPoint clickPos) const { return false; };
106
robertphillips 2016/08/19 17:50:19 Why not a relativeX too ? An SkPoint ?
107 // The y-coordinate of the control relative to it's parent
108 SkScalar fRelativeY;
109 };
110
111 class ParentControl : public Control { // Interface for all controls that have c hildren
112 public:
robertphillips 2016/08/19 17:50:20 const SkString& ? use INHERITED ?
dvonbeck 2016/08/19 18:25:17 Done.
113 ParentControl(SkString name) : Control(name) {}
114
115 // Adds a child
116 virtual void add(sk_sp<Control> control) = 0;
117
118 // Returns the control's width. Used to propagate width down to components t hat don't specify it
119 virtual SkScalar width() const = 0;
robertphillips 2016/08/19 17:50:19 private: INHERITED ?
dvonbeck 2016/08/19 18:25:17 Done.
120 };
121
122 class ControlPanel : public ParentControl {
123 public:
124
125 ControlPanel(SkScalar width)
robertphillips 2016/08/19 17:50:19 tabbed too far over
dvonbeck 2016/08/19 18:25:18 Done.
126 : ParentControl(SkString("ControlPanel"))
127 , fWidth(width)
128 , fHeight(0.0f)
129 , fSelectedControl(-1) {}
130
131 // Width unspecified, expectation is inheritance from parent
132 ControlPanel() : ControlPanel(-1.0f) {}
133
134 // Use this for introducing clicks on a ControlPanel from outside of the fra mework. It
135 // propagates click release or position down the chain. Returns false when c lick capture is
136 // being released.
137 bool inClick(SkView::Click *inClick) {
138 if (SkView::Click::State::kUp_State == inClick->fState) {
139 this->onClickRelease();
140 return false;
141 }
142 return this->click(inClick->fCurr);
143 }
144
145 // Add children
146 void add(sk_sp<Control> control) override {
147 SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depend s on immutability
148 fControls.push_back(control);
149 control->setParent(this, fHeight);
150 fHeight += control->height();
151 }
152
153 SkScalar width() const override {
154 return fParent ? fParent->width() : fWidth; // Width inherited from pare nt if there is one
155 }
156
157 SkScalar height() const override {
158 return fHeight;
159 }
160
robertphillips 2016/08/19 17:50:20 overlength
dvonbeck 2016/08/19 18:25:17 Done.
161 void onClickRelease() override { // Propagate click release to selected cont rol, deselect control
robertphillips 2016/08/19 17:50:19 add newlines and brackets
dvonbeck 2016/08/19 18:25:17 Done.
162 if (fSelectedControl >= 0) fControls[fSelectedControl]->onClickRelease() ;
163 fSelectedControl = -1;
164 }
165
166 // Propagate onSetParent() down to children, some might need fParent->width( ) refresh
167 void onSetParent() override {
168 for (int i = 0; i < fControls.count(); i++) {
169 fControls[i]->onSetParent();
170 }
171 }
172
173 // Holds a vertical shelf of controls. Can't be hierarchy root if not given a width value.
174 static sk_sp<ParentControl> Make() {
175 return sk_sp<ParentControl>(new ControlPanel());
176 }
177
178 // Holds a vertical shelf of controls. Only control that can be hooked from outside the
179 // framework.
180 static sk_sp<ParentControl> Make(SkScalar width) {
181 return sk_sp<ParentControl>(new ControlPanel(width));
182 }
183
184 protected:
185 // Returns true if control panel has mouse captured, false when it is ready to release
186 // capture
robertphillips 2016/08/19 17:50:19 const & ?
dvonbeck 2016/08/19 18:25:16 Done.
187 bool onClick(SkPoint click) override {
188
189 if (fSelectedControl == -1) { // If no child control selected, check eve ry child
190 for (int i = 0; i < fControls.count(); i++) {
191 if (fControls[i]->isInCtrlRegion(click)) {
192 fSelectedControl = i;
193 break;
194 }
195 }
196 }
197
198 if (fSelectedControl >= 0) { // If child control selected, propagate cli ck
199 bool keepSelection = fControls[fSelectedControl]->click(click);
200 if (!keepSelection) {
201 fSelectedControl = -1;
202 }
203 return keepSelection;
204 }
205
206 return false;
207 }
208
209 // Draw all children
210 void onDrawContent(SkCanvas* canvas) override {
211 canvas->save();
212 for (int i = 0; i < fControls.count(); i++) {
213 fControls[i]->drawContent(canvas);
214 }
215 canvas->restore();
216 }
217
218 // Check all children's control regions
219 bool onIsInCtrlRegion(SkPoint clickPos) const override {
egdaniel 2016/08/19 17:56:35 const &
dvonbeck 2016/08/19 18:25:17 Done.
220 for (int i = 0; i < fControls.count(); i++) {
robertphillips 2016/08/19 17:50:20 \ns and brackets
dvonbeck 2016/08/19 18:25:16 Done.
221 if (fControls[i]->isInCtrlRegion(clickPos)) return true;
222 }
223
224 return false;
225 }
226
227 private:
228 SkScalar fWidth;
229 SkScalar fHeight;
230
231 SkTArray<sk_sp<Control>> fControls;
232 int fSelectedControl;
233 };
234
235 class DiscreteSliderControl : public Control {
236 public:
robertphillips 2016/08/19 17:50:19 ovveride ?
dvonbeck 2016/08/19 18:25:17 Done.
237 SkScalar height() const { //ovverride}
238 return 2.0f * kLabelHeight;
239 }
240
241 // Set width-dependant variables when new parent is set
242 void onSetParent() override {
robertphillips 2016/08/19 17:50:19 one line ?
dvonbeck 2016/08/19 18:25:17 Done.
243 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight,
244 fParent->width(), kSliderHeight);
245 fSliderRange = fParent->width() - kSliderWidth;
246 }
247
248 /* Make a slider for an integer value. Snaps to discrete positions.
249 *
250 * @params name The name of the control, displayed in the label
251 * @params output Pointer to the integer that will be set by the slider
252 * @params min Min value for output.
253 * @params max Max value for output.
254 */
255 static sk_sp<Control> Make(SkString name, int* output, int min, int max) {
256 return sk_sp<Control>(new DiscreteSliderControl(name, output, min, max)) ;
257 }
258
259 protected:
260 void onDrawContent(SkCanvas* canvas) override {
261 SkASSERT(fParent);
262 int numChoices = fMax - fMin + 1;
263 fSlider.offsetTo(fSliderRange * ( (*fOutput)/SkIntToScalar(numChoices)
264 + 1.0f/(2.0f * numChoices) ),
265 fSlider.fTop);
266
267 SkString valueStr;
268 valueStr.appendScalar(*fOutput);
269 this->drawLabel(canvas, valueStr);
270
271 SkPaint sliderPaint;
272 sliderPaint.setColor(0xFFF3F3F3);
273 canvas->drawRect(fSlider, sliderPaint);
274
275 SkPaint ctrlRegionPaint;
276 ctrlRegionPaint.setColor(0xFFFFFFFF);
277 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
278 ctrlRegionPaint.setStrokeWidth(2.0f);
279 canvas->drawRect(fCtrlRegion, ctrlRegionPaint);
280 }
281
282 bool onClick(SkPoint clickPos) override {
egdaniel 2016/08/19 17:56:35 const &
dvonbeck 2016/08/19 18:25:17 Done.
283 SkASSERT(fParent);
284 SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange);
285 int numChoices = fMax - fMin + 1;
286 *fOutput = SkTMin(SkScalarFloorToInt(numChoices * x / fSliderRange) + fM in, fMax);
287
288 return true;
289 }
290
robertphillips 2016/08/19 17:50:19 const & ?
dvonbeck 2016/08/19 18:25:17 Done.
291 bool onIsInCtrlRegion(SkPoint clickPos) const override {
292 SkASSERT(fParent);
293 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1 , 1));
294 }
295
296 private:
297 DiscreteSliderControl(SkString name, int* output, int min, int max)
robertphillips 2016/08/19 17:50:20 use INHERITED here ?
dvonbeck 2016/08/19 18:25:18 Done.
298 : Control(name)
299 , fOutput(output)
300 , fMin(min)
301 , fMax(max) {
302 fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight) ;
303 }
304
305 int* fOutput;
306 int fMin;
307 int fMax;
308 SkRect fSlider; // The rectangle that slides
309 // The region in which the rectangle slides. Also the region in which mouse is caputred
310 SkRect fCtrlRegion;
311 SkScalar fSliderRange; // The width in pixels over which the slider can slid e
312
313 static constexpr SkScalar kSliderHeight = 20.0f;
314 static constexpr SkScalar kSliderWidth = 10.0f;
robertphillips 2016/08/19 17:50:19 private: INHERITED ?
dvonbeck 2016/08/19 18:25:17 Done.
315 };
316
317 class ControlSwitcher : public ParentControl {
318 public:
319 // Add children
320 void add(sk_sp<Control> control) override {
321 SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depend s on immutability
322 fControls.push_back(control);
323 control->setParent(this, kSelectorHeight);
324 fHeight = SkMaxScalar(fHeight, control->height()); // Setting height to max child height.
325 }
326
327 SkScalar width() const override { return fParent ? (fParent->width()) : 0; }
328
329 SkScalar height() const override {
330 return fHeight;
331 }
332
333 // Propagate onClickRelease to control that currently captures mouse
334 void onClickRelease() override {
335 if (fCtrlOnClick) {
336 fCtrlOnClick->onClickRelease();
337 }
338 fCtrlOnClick = nullptr;
339 }
340
341 void onSetParent() override {
342 for (int i = 0; i < fControls.count(); i++) {
343 fControls[i]->onSetParent(); // Propagate to children
344 }
345
346 // Finalize control selector
347 // TODO can be moved to constructor if list-initialized
348 if (!finalizedChildren) {
349 fControlSelector = DiscreteSliderControl::Make(
350 SkString(fName), &fSelectedControl, 0, fControls.count()-1);
351 fControlSelector->setParent(this, 0.0f);
352 fHeight += kSelectorHeight;
353
354 SkASSERT(fControlSelector->height() <= kSelectorHeight);
355 }
356 }
357
358 /* A set of a selector and a list of controls. Displays the control from the list of controls
359 * with the index set by the aforementioned selector.
360 *
361 * @param name The name of the switcher. Will be displayed in the selector's label.
362 */
robertphillips 2016/08/19 17:50:19 const & ?
dvonbeck 2016/08/19 18:25:17 Done.
363 static sk_sp<ParentControl> Make(SkString name) {
364 return sk_sp<ParentControl>(new ControlSwitcher(name));
365 }
366
367 protected:
368 // Draw selector and currently selected control
369 void onDrawContent(SkCanvas* canvas) override {
370 fControlSelector->drawContent(canvas);
371 fControls[fSelectedControl]->drawContent(canvas);
372 }
373
374 // Returns true if control panel has mouse captured, false when it is ready to release
375 // capture
robertphillips 2016/08/19 17:50:19 const & ?
dvonbeck 2016/08/19 18:25:17 Done.
376 bool onClick(SkPoint click) override {
377 if (!fCtrlOnClick) {
378 if (fControlSelector->isInCtrlRegion(click)) {
379 fCtrlOnClick = fControlSelector.get();
380 } else if (fControls[fSelectedControl]->isInCtrlRegion(click)) {
381 fCtrlOnClick = fControls[fSelectedControl].get();
382 }
383 }
384 if (fCtrlOnClick) {
385 return fCtrlOnClick->click(click);
386 }
387
388 return false;
389 }
390
391 // Is in control region of selector or currently selected control
392 bool onIsInCtrlRegion(SkPoint clickPos) const override {
393 if (fControlSelector->isInCtrlRegion(clickPos)) return true;
robertphillips 2016/08/19 17:50:19 \ns and brackets
dvonbeck 2016/08/19 18:25:18 Done.
394 if (fControls[fSelectedControl]->isInCtrlRegion(clickPos)) return true;
395
396 return false;
397 }
398
399 private:
robertphillips 2016/08/19 17:50:19 one line ? const SkString& ? use INHERITED here ?
dvonbeck 2016/08/19 18:25:17 Doesn't fit in one line, rest are done
400 ControlSwitcher(SkString name)
401 : ParentControl(name)
402 , fHeight(0.0)
403 , fSelectedControl(0)
404 , fCtrlOnClick(nullptr){}
405
406 bool finalizedChildren = false;
407
408 sk_sp<Control> fControlSelector;
409 SkScalar fHeight;
410 SkTArray<sk_sp<Control>> fControls;
411 int fSelectedControl;
412
413 Control* fCtrlOnClick;
414
415 static constexpr SkScalar kSelectorHeight = 40.0f;
416 };
417
418 class ContinuousSliderControl : public Control {
419 public:
420 SkScalar height() const override {
421 return 2.0f * kLabelHeight;
422 }
423
424 void onSetParent() {
425 fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight) ;
426 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight,
427 fParent->width(), kSliderHeight);
428 fSliderRange = fParent->width() - kSliderWidth;
429 }
430
431 /* Make a slider for an SkScalar.
432 *
433 * @params name The name of the control, displayed in the label
434 * @params output Pointer to the SkScalar that will be set by the slider
435 * @params min Min value for output
436 * @params max Max value for output
437 */
438 static sk_sp<Control> Make(SkString name, SkScalar* output, SkScalar min, Sk Scalar max) {
439 return sk_sp<Control>(new ContinuousSliderControl(name, output, min, max) );
440 }
441
442 protected:
443 void onDrawContent(SkCanvas* canvas) override {
444 SkASSERT(fParent);
445 SkScalar x = fSliderRange * (*fOutput - fMin) / (fMax - fMin);
446 fSlider.offsetTo(SkScalarPin(x, 0.0f, fSliderRange), fSlider.fTop);
447
448 SkString valueStr;
449 valueStr.appendScalar(*fOutput);
450 this->drawLabel(canvas, valueStr);
451
452 SkPaint sliderPaint;
453 sliderPaint.setColor(0xFFF3F3F3);
454 canvas->drawRect(fSlider, sliderPaint);
455
456 SkPaint ctrlRegionPaint;
457 ctrlRegionPaint.setColor(0xFFFFFFFF);
458 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
459 ctrlRegionPaint.setStrokeWidth(2.0f);
460 canvas->drawRect(fCtrlRegion, ctrlRegionPaint);
461 }
462
463 bool onClick(SkPoint clickPos) override {
464 SkASSERT(fParent);
465 SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange);
466 *fOutput = (x/fSliderRange) * (fMax - fMin) + fMin;
467 return true;
468 }
469
470 bool onIsInCtrlRegion(SkPoint clickPos) const override {
471 SkASSERT(fParent);
472 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1 , 1));
473 }
474
475 private:
476 ContinuousSliderControl(SkString name, SkScalar* output, SkScalar min, SkSca lar max)
477 : Control(name)
478 , fOutput(output)
479 , fMin(min)
480 , fMax(max) {}
481
482 SkScalar* fOutput;
483 SkScalar fMin;
484 SkScalar fMax;
485 SkRect fSlider;
486 SkRect fCtrlRegion;
487 SkScalar fSliderRange;
488
489 static constexpr SkScalar kSliderHeight = 20.0f;
490 static constexpr SkScalar kSliderWidth = 10.0f;
491 };
492
493 class RadialDirectionControl : public Control {
494 public:
495 SkScalar height() const override {
496 return kLabelHeight + 2.0f * kRegionRadius;
497 }
498
499 /* Make a direction selector.
500 *
501 * @params name The name of the control, displayed in the label
502 * @params output Pointer to the SkVector that will be set by the slider
503 */
504 static sk_sp<Control> Make(SkString name, SkVector* output) {
505 return sk_sp<Control>(new RadialDirectionControl(name, output));
506 }
507
508 protected:
509 void onDrawContent(SkCanvas* canvas) override {
510 SkASSERT(fParent);
511
512 SkString valueStr;
513 valueStr.appendf("%.2f, %.2f", fOutput->fX, fOutput->fY);
514 this->drawLabel(canvas, valueStr);
515
516 SkPoint lineEnd = SkPoint::Make(fCtrlRegion.centerX(), fCtrlRegion.cente rY())
517 + (*fOutput * (kRegionRadius - kCapRadius));
518 SkPaint linePaint;
519 linePaint.setColor(0xFFF3F3F3);
520 linePaint.setStrokeWidth(kStrokeWidth);
521 linePaint.setAntiAlias(true);
522 linePaint.setStrokeCap(SkPaint::kRound_Cap);
523 canvas->drawLine(fCtrlRegion.centerX(), fCtrlRegion.centerY(),
524 lineEnd.fX, lineEnd.fY, linePaint);
525
526 SkPaint ctrlRegionPaint;
527 ctrlRegionPaint.setColor(0xFFFFFFFF);
528 ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
529 ctrlRegionPaint.setStrokeWidth(2.0f);
530 ctrlRegionPaint.setAntiAlias(true);
531 canvas->drawCircle(fCtrlRegion.centerX(), fCtrlRegion.centerY(), kRegion Radius,
532 ctrlRegionPaint);
533 }
534
535 bool onClick(SkPoint clickPos) override {
536 SkASSERT(fParent);
537 fOutput->fX = clickPos.fX - fCtrlRegion.centerX();
538 fOutput->fY = clickPos.fY - fCtrlRegion.centerY();
539 fOutput->normalize();
540
541 return true;
542 }
543
544 bool onIsInCtrlRegion(SkPoint clickPos) const override {
545 SkASSERT(fParent);
546 return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY,
547 1, 1));
548 }
549
550 private:
551 RadialDirectionControl(SkString name, SkVector* output)
552 : Control(name)
553 , fOutput(output) {
554 fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, kRegionRadius * 2.0f, kRegionRadius * 2.0f);
egdaniel 2016/08/19 17:56:35 100 chars.
dvonbeck 2016/08/19 18:25:17 Done.
555 }
556
557 SkVector* fOutput;
558 SkRect fCtrlRegion;
559
560 static constexpr SkScalar kRegionRadius = 50.0f;
561 static constexpr SkScalar kStrokeWidth = 6.0f;
562 static constexpr SkScalar kCapRadius = kStrokeWidth / 2.0f;
563 };
564
565 class ColorDisplay: public Control {
566 public:
567 SkScalar height() const override {
568 return kHeight;
569 }
570
571 void onSetParent() override {
572 fDisplayRect = SkRect::MakeXYWH(0.0f, kPadding, fParent->width(), kHeigh t - kPadding);
573 }
574
575 /* Make a display that shows an SkColor3f.
576 *
577 * @params output Pointer to the SkColor3f that will be displayed
578 */
579 static sk_sp<Control> Make(SkColor3f* input) {
580 return sk_sp<Control>(new ColorDisplay(SkString("ColorDisplay"), input)) ;
581 }
582
583 protected:
584 void onDrawContent(SkCanvas* canvas) override {
585 SkASSERT(fParent);
586
587 SkPaint displayPaint;
588 displayPaint.setColor(SkColor4f::FromColor3f(*fInput, 1.0f).toSkColor()) ;
589 canvas->drawRect(fDisplayRect, displayPaint);
590 }
591
592 private:
593 ColorDisplay(SkString name, SkColor3f* input)
594 : Control(name)
595 , fInput(input) {}
596
597 SkColor3f* fInput;
598 SkRect fDisplayRect;
599
600 static constexpr SkScalar kHeight = 24.0f;
601 static constexpr SkScalar kPadding = 4.0f;
602 };
14 603
15 class BevelView : public SampleView { 604 class BevelView : public SampleView {
16 public: 605 public:
17 BevelView() 606 BevelView()
18 : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize)) 607 : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize))
19 , fRedLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.6f, 0.45f , 0.3f), 608 , fControlPanel(kCtrlRange) {
20 SkVector3::Make(0.0f, -5.0f , 1.0f)))
21 , fBlueLight(SkLights::Light::MakeDirectional(SkColor3f::Make(0.3f, 0.45 f, 0.6f),
22 SkVector3::Make(0.0f, 5.0f , 1.0f))) {
23 this->setBGColor(0xFF666868); // Slightly colorized gray for contrast 609 this->setBGColor(0xFF666868); // Slightly colorized gray for contrast
24 610
25 // Lights
26 SkLights::Builder builder;
27 builder.add(fRedLight);
28 builder.add(fBlueLight);
29 builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4 f)));
30 fLights = builder.finish();
31
32 // Controls 611 // Controls
33 612 fBevelWidth = 25.0f;
34 SkScalar currY = kSliderHeight; 613 fBevelHeight = 25.0f;
35 614 fBevelType = SkNormalSource::BevelType::kLinear;
36 const SkScalar kWidthCtrlInitialPos = 0.2f; 615
37 fCtrlRangeRects[0] = SkRect::MakeXYWH(0.0f, currY, 616 int currLight = 0;
38 kCtrlRange + kSliderWidth, 617 fLightDefs[currLight++] =
39 kSliderHeight); 618 {SkVector::Make(0.0f, 1.0f), 1.0f, SkColor3f::Make(0.6f, 0.45f, 0.3f)};
40 fWidthCtrlRect = SkRect::MakeXYWH(kWidthCtrlInitialPos * kCtrlRange, cur rY, 619 fLightDefs[currLight++] =
41 kSliderWidth, kSliderHeight); 620 {SkVector::Make(0.0f, -1.0f), 1.0f, SkColor3f::Make(0.3f, 0.45f, 0.6f)};
42 fBevelWidth = kBevelWidthMax * kWidthCtrlInitialPos; 621 fLightDefs[currLight++] =
43 currY += 2 * kSliderHeight; 622 {SkVector::Make(1.0f, 0.0f), 1.0f, SkColor3f::Make(0.0f, 0.0f, 0 .0f)};
44 623 // Making sure we initialized all lights
45 const SkScalar kHeightCtrlInitialPos = 0.75f; 624 SkASSERT(currLight == kNumLights);
46 fCtrlRangeRects[1] = SkRect::MakeXYWH(0.0f, currY, 625
47 kCtrlRange + kSliderWidth, 626 fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelWidth"), &fBevelWidth,
48 kSliderHeight); 627 1.0f, kShapeBoundsSize)) ;
49 fHeightCtrlRect = SkRect::MakeXYWH(kHeightCtrlInitialPos * kCtrlRange, c urrY, 628 fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelHeight"), &fBevelHeight,
50 kSliderWidth, kSliderHeight); 629 -50.0f, 50.0f));
robertphillips 2016/08/19 17:50:19 That's and exciting cast there. I propose you actu
dvonbeck 2016/08/19 18:25:16 Done.
51 // Mapping from (0, 1) to (-1, 1) 630 fControlPanel.add(DiscreteSliderControl::Make(SkString("BevelType"), (in t*)&fBevelType,
52 fBevelHeight = kBevelHeightMax * (kHeightCtrlInitialPos * 2.0f - 1.0f); 631 0, 2));
53 currY += 2 * kSliderHeight; 632 sk_sp<ParentControl> lightCtrlSelector = ControlSwitcher::Make(SkString( "SelectedLight"));
54 633 for (int i = 0; i < kNumLights; i++) {
55 const SkScalar kTypeCtrlInitialPos = 1.0f / (2.0f * kBevelTypeCount); 634 SkString name("Light");
56 fCtrlRangeRects[2] = SkRect::MakeXYWH(0.0f, currY, 635 name.appendS32(i);
57 kCtrlRange + kSliderWidth, 636 sk_sp<ParentControl> currLightPanel = ControlPanel::Make();
58 kSliderHeight); 637 SkString dirName(name);
59 fTypeCtrlRect = SkRect::MakeXYWH(kTypeCtrlInitialPos * kCtrlRange, currY , 638 dirName.append("Dir");
60 kSliderWidth, kSliderHeight); 639 currLightPanel->add(RadialDirectionControl::Make(dirName, &(fLightDe fs[i].fDirXY)));
61 fBevelType = (SkNormalSource::BevelType) SkScalarFloorToInt(kTypeCtrlIni tialPos); 640 SkString heightName(name);
62 currY += 2 * kSliderHeight; 641 heightName.append("Height");
63 642 currLightPanel->add(ContinuousSliderControl::Make(heightName, &(fLig htDefs[i].fDirZ),
64 fSelectedCtrlRect = nullptr; 643 0.0f, 2.0f));
644 SkString redName(name);
645 redName.append("Red");
646 currLightPanel->add(ContinuousSliderControl::Make(redName, &(fLightD efs[i].fColor.fX),
647 0.0f, 1.0f));
648 SkString greenName(name);
649 greenName.append("Green");
650 currLightPanel->add(ContinuousSliderControl::Make(greenName, &(fLigh tDefs[i].fColor.fY),
651 0.0f, 1.0f));
652 SkString blueName(name);
653 blueName.append("Blue");
654 currLightPanel->add(ContinuousSliderControl::Make(blueName, &(fLight Defs[i].fColor.fZ),
655 0.0f, 1.0f));
656 currLightPanel->add(ColorDisplay::Make(&(fLightDefs[i].fColor)));
657 lightCtrlSelector->add(currLightPanel);
658 }
659 fControlPanel.add(lightCtrlSelector);
660
661 fControlPanelSelected = false;
65 fDirtyNormalSource = true; 662 fDirtyNormalSource = true;
66 663
67 fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", S kFontStyle()); 664 fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", S kFontStyle());
68 } 665 }
69 666
70 protected: 667 protected:
71 bool onQuery(SkEvent *evt) override { 668 bool onQuery(SkEvent *evt) override {
72 if (SampleCode::TitleQ(*evt)) { 669 if (SampleCode::TitleQ(*evt)) {
73 SampleCode::TitleR(evt, "Bevel"); 670 SampleCode::TitleR(evt, "Bevel");
74 return true; 671 return true;
(...skipping 30 matching lines...) Expand all
105 default: 702 default:
106 SkDEBUGFAIL("Invalid shape enum for drawShape"); 703 SkDEBUGFAIL("Invalid shape enum for drawShape");
107 } 704 }
108 705
109 canvas->restore(); 706 canvas->restore();
110 } 707 }
111 708
112 void onDrawContent(SkCanvas *canvas) override { 709 void onDrawContent(SkCanvas *canvas) override {
113 710
114 canvas->save(); 711 canvas->save();
115 canvas->resetMatrix(); // Force static controls and labels 712 canvas->resetMatrix(); // Force static control panel position
713 fControlPanel.drawContent(canvas);
714 canvas->restore();
116 715
117 // Draw controls 716 SkLights::Builder builder;
118 717 for (int i = 0; i < kNumLights; i++) {
119 SkPaint ctrlRectPaint; 718 builder.add(SkLights::Light::MakeDirectional(fLightDefs[i].fColor,
120 ctrlRectPaint.setColor(0xFFF3F3F3); 719 SkPoint3::Make(fLightDe fs[i].fDirXY.fX,
121 canvas->drawRect(fWidthCtrlRect, ctrlRectPaint); 720 fLightDe fs[i].fDirXY.fY,
122 canvas->drawRect(fHeightCtrlRect, ctrlRectPaint); 721 fLightDe fs[i].fDirZ)));
123 canvas->drawRect(fTypeCtrlRect, ctrlRectPaint);
124
125 SkPaint ctrlRectRangePaint;
126 ctrlRectRangePaint.setColor(0xFFFFFFFF);
127 ctrlRectRangePaint.setStyle(SkPaint::kStroke_Style);
128 ctrlRectRangePaint.setStrokeWidth(2.0f);
129
130 for (size_t i = 0; i < kNumControls; i++) {
131 canvas->drawRect(fCtrlRangeRects[i], ctrlRectRangePaint);
132 } 722 }
133 723 builder.add(SkLights::Light::MakeAmbient(SkColor3f::Make(0.4f, 0.4f, 0.4 f)));
134 // Draw labels 724 fLights = builder.finish();
egdaniel 2016/08/19 17:56:35 Does this correctly destroy the old lights in fLig
dvonbeck 2016/08/19 18:25:17 Yes, SkLights is backed by SkTArray of lights. Des
135 constexpr SkScalar kTextSize = 12.0f;
136 SkString widthLabel, heightLabel, typeLabel;
137 SkPaint labelPaint;
138 labelPaint.setTypeface(fLabelTypeface);
139 labelPaint.setAntiAlias(true);
140 labelPaint.setColor(0xFFFFFFFF);
141 labelPaint.setTextSize(kTextSize);
142
143 widthLabel.appendf("BevelWidth: %f", fBevelWidth);
144 heightLabel.appendf("BevelHeight: %f", fBevelHeight);
145 typeLabel.append("BevelType: ");
146
147 switch (fBevelType) {
148 case SkNormalSource::BevelType::kLinear:
149 typeLabel.append("Linear");
150 break;
151 case SkNormalSource::BevelType::kRoundedIn:
152 typeLabel.append("RoundedIn");
153 break;
154 case SkNormalSource::BevelType::kRoundedOut:
155 typeLabel.append("RoundedOut");
156 break;
157 }
158
159 canvas->drawText(widthLabel.c_str(), widthLabel.size(), 0,
160 fWidthCtrlRect.fTop - kTextSize/2.0f, labelPaint);
161 canvas->drawText(heightLabel.c_str(), heightLabel.size(), 0,
162 fHeightCtrlRect.fTop - kTextSize/2.0f, labelPaint);
163 canvas->drawText(typeLabel.c_str(), typeLabel.size(), 0,
164 fTypeCtrlRect.fTop - kTextSize/2.0f, labelPaint);
165
166 canvas->restore(); // Return to modified matrix when drawing shapes
167 725
168 // Draw shapes 726 // Draw shapes
169 SkScalar xPos = kCtrlRange + 25.0f; 727 SkScalar xPos = kCtrlRange + 25.0f;
170 SkScalar yPos = fShapeBounds.height(); 728 SkScalar yPos = fShapeBounds.height();
171 for (Shape shape : { kCircle_Shape, kRect_Shape }) { 729 for (Shape shape : { kCircle_Shape, kRect_Shape }) {
172 canvas->save(); 730 canvas->save();
173 canvas->translate(xPos, yPos); 731 canvas->translate(xPos, yPos);
174 this->drawShape(shape, canvas); 732 this->drawShape(shape, canvas);
175 canvas->restore(); 733 canvas->restore();
176 734
177 xPos += 1.2f * fShapeBounds.width(); 735 xPos += 1.2f * fShapeBounds.width();
178 } 736 }
179 } 737 }
180 738
181 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { 739 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride {
182 return new SkView::Click(this); 740 return new SkView::Click(this);
183 } 741 }
184 742
185 bool onClick(Click *click) override { 743 bool onClick(Click *click) override {
186 SkScalar x = click->fCurr.fX; 744 // Control panel mouse handling
187 SkScalar y = click->fCurr.fY; 745 fControlPanelSelected = fControlPanel.inClick(click);
188 746
189 SkScalar dx = x - click->fPrev.fX; 747 if (fControlPanelSelected) { // Control modification
190 SkScalar dy = y - click->fPrev.fY;
191
192 // Control deselection
193 if (Click::State::kUp_State == click->fState) {
194 fSelectedCtrlRect = nullptr;
195 return true;
196 }
197
198 // Control selection
199 if (nullptr == fSelectedCtrlRect && Click::State::kDown_State == click-> fState) {
200 if (fWidthCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
201 fSelectedCtrlRect = &fWidthCtrlRect;
202 } else if (fHeightCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
203 fSelectedCtrlRect = &fHeightCtrlRect;
204 } else if (fTypeCtrlRect.contains(SkRect::MakeXYWH(x, y, 1, 1))) {
205 fSelectedCtrlRect = &fTypeCtrlRect;
206 }
207 }
208
209 if (nullptr != fSelectedCtrlRect) { // Control modification
210 fSelectedCtrlRect->offsetTo(SkScalarPin(x, 0.0f, kCtrlRange), fSelec tedCtrlRect->fTop);
211
212 fBevelHeight = (fHeightCtrlRect.fLeft / kCtrlRange) * kBevelHeightMa x * 2.0f
213 - kBevelHeightMax;
214 fBevelWidth = (fWidthCtrlRect.fLeft / kCtrlRange) * kBevelWidthMax;
215 fBevelType = (SkNormalSource::BevelType)SkTMin(
216 SkScalarFloorToInt(kBevelTypeCount * fTypeCtrlRect.fLeft / k CtrlRange),
217 kBevelTypeCount - 1);
218
219 // Snap type controls to 3 positions
220 fTypeCtrlRect.offsetTo(kCtrlRange * ( ((int)fBevelType)/SkIntToScala r(kBevelTypeCount)
221 + 1.0f/(2.0f * kBevelTypeCount ) ),
222 fTypeCtrlRect.fTop);
223
224 // Ensuring width is non-zero
225 fBevelWidth = SkMaxScalar(1.0f, fBevelWidth);
226
227 fDirtyNormalSource = true; 748 fDirtyNormalSource = true;
228 749
229 this->inval(nullptr); 750 this->inval(nullptr);
230 return true; 751 return true;
231 } else { // Moving light
232 if (dx != 0 || dy != 0) {
233 float recipX = 1.0f / kAppWidth;
234 float recipY = 1.0f / kAppHeight;
235
236 if (0 == click->fModifierKeys) { // No modifier
237 fBlueLight = SkLights::Light::MakeDirectional(fBlueLight.col or(),
238 SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0 f,
239 (kAppHeight/2.0f - y) * recipY * -3. 0f,
240 1.0f));
241 } else if (1 == click->fModifierKeys) { // Shift key
242 fRedLight = SkLights::Light::MakeDirectional(fRedLight.color (),
243 SkVector3::Make((kAppWidth/2.0f - x) * recipX * -3.0 f,
244 (kAppHeight/2.0f - y) * recipY * -3. 0f,
245 1.0f));
246 }
247
248 SkLights::Builder builder;
249 builder.add(fRedLight);
250 builder.add(fBlueLight);
251 builder.add(SkLights::Light::MakeAmbient(
252 SkColor3f::Make(0.4f, 0.4f, 0.4f)));
253 fLights = builder.finish();
254
255 this->inval(nullptr);
256 }
257 return true;
258 } 752 }
259 753
754 // TODO move shapes
755 this->inval(nullptr);
260 return true; 756 return true;
261 } 757 }
262 758
263 private: 759 private:
264 static constexpr int kNumTestRects = 3; 760 static constexpr int kNumTestRects = 3;
265 761
266 static constexpr SkScalar kAppWidth = 400.0f;
267 static constexpr SkScalar kAppHeight = 400.0f;
268 static constexpr SkScalar kShapeBoundsSize = 120.0f; 762 static constexpr SkScalar kShapeBoundsSize = 120.0f;
269 763
270 static constexpr SkScalar kCtrlRange = 150.0f; 764 static constexpr SkScalar kCtrlRange = 150.0f;
271 static constexpr SkScalar kBevelWidthMax = kShapeBoundsSize;
272 static constexpr SkScalar kBevelHeightMax = 50.0f;
273 static constexpr int kBevelTypeCount = 3;
274 765
275 static constexpr SkScalar kSliderHeight = 20.0f; 766 static constexpr int kNumLights = 3;
276 static constexpr SkScalar kSliderWidth = 10.0f;
277 767
278 const SkRect fShapeBounds; 768 const SkRect fShapeBounds;
279 769
280 static constexpr int kNumControls = 3;
281 SkRect fCtrlRangeRects[kNumControls];
282 SkRect* fSelectedCtrlRect;
283 SkRect fWidthCtrlRect;
284 SkRect fHeightCtrlRect;
285 SkRect fTypeCtrlRect;
286
287 SkScalar fBevelWidth; 770 SkScalar fBevelWidth;
288 SkScalar fBevelHeight; 771 SkScalar fBevelHeight;
289 SkNormalSource::BevelType fBevelType; 772 SkNormalSource::BevelType fBevelType;
290 sk_sp<SkNormalSource> fNormalSource; 773 sk_sp<SkNormalSource> fNormalSource;
291 bool fDirtyNormalSource; 774 bool fDirtyNormalSource;
292 775
293 sk_sp<SkLights> fLights; 776 sk_sp<SkLights> fLights;
294 SkLights::Light fRedLight; 777
295 SkLights::Light fBlueLight; 778 struct LightDef {
779 SkVector fDirXY;
780 SkScalar fDirZ;
781 SkColor3f fColor;
782
783 LightDef() {}
784 LightDef(SkVector dirXY, SkScalar dirZ, SkColor3f color)
785 : fDirXY(dirXY)
786 , fDirZ(dirZ)
787 , fColor(color) {}
788 };
789 LightDef fLightDefs[kNumLights];
790
791 ControlPanel fControlPanel;
792 bool fControlPanelSelected;
296 793
297 sk_sp<SkTypeface> fLabelTypeface; 794 sk_sp<SkTypeface> fLabelTypeface;
298 795
299 typedef SampleView INHERITED; 796 typedef SampleView INHERITED;
300 }; 797 };
301 798
302 ////////////////////////////////////////////////////////////////////////////// 799 //////////////////////////////////////////////////////////////////////////////
303 800
304 static SkView* MyFactory() { return new BevelView; } 801 static SkView* MyFactory() { return new BevelView; }
305 static SkViewRegister reg(MyFactory); 802 static SkViewRegister reg(MyFactory);
306 803
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698