|  | /* | 
|  | * Copyright 2019 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "Sample.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "SkFont.h" | 
|  | #include "SkFontMetrics.h" | 
|  | #include "SkPath.h" | 
|  |  | 
|  | #include "SkSGDraw.h" | 
|  | #include "SkSGGroup.h" | 
|  | #include "SkSGPaint.h" | 
|  | #include "SkSGRect.h" | 
|  | #include "SkSGScene.h" | 
|  |  | 
|  | struct PerNodeInfo { | 
|  | // key | 
|  | sksg::Draw* fDraw; | 
|  |  | 
|  | // value(s) | 
|  | sksg::GeometryNode* fGeo; | 
|  | sksg::PaintNode*    fPaint; | 
|  | }; | 
|  |  | 
|  | class SampleSG : public Sample { | 
|  | SkTDArray<PerNodeInfo> fSideCar; | 
|  | sk_sp<sksg::Group> fGroup; | 
|  | std::unique_ptr<sksg::Scene> fScene; | 
|  |  | 
|  | PerNodeInfo* findInfo(sksg::Draw* key) { | 
|  | for (int i = 0; i < fSideCar.count(); ++i) { | 
|  | if (fSideCar[i].fDraw == key) { | 
|  | return &fSideCar[i]; | 
|  | } | 
|  | } | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void appendNode(sk_sp<sksg::Draw> d, sk_sp<sksg::GeometryNode> g, sk_sp<sksg::PaintNode> p) { | 
|  | fGroup->addChild(d); | 
|  | auto sc = fSideCar.append(); | 
|  | sc->fDraw  = d.get(); | 
|  | sc->fGeo   = g.get(); | 
|  | sc->fPaint = p.get(); | 
|  | } | 
|  |  | 
|  | public: | 
|  | SampleSG() { | 
|  | fGroup = sksg::Group::Make(); | 
|  |  | 
|  | fScene = sksg::Scene::Make(fGroup, sksg::AnimatorList()); | 
|  |  | 
|  | auto r = sksg::Rect::Make({20, 20, 400, 300}); | 
|  | auto p = sksg::Color::Make(SK_ColorRED); | 
|  | auto d = sksg::Draw::Make(r, p); | 
|  | this->appendNode(d, r, p); | 
|  |  | 
|  | r = sksg::Rect::Make({60, 70, 300, 400}); | 
|  | p = sksg::Color::Make(SK_ColorBLUE); | 
|  | d = sksg::Draw::Make(r, p); | 
|  | this->appendNode(d, r, p); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | bool onQuery(Sample::Event* evt) override { | 
|  | if (Sample::TitleQ(*evt)) { | 
|  | Sample::TitleR(evt, "SceneGraph"); | 
|  | return true; | 
|  | } | 
|  | return this->INHERITED::onQuery(evt); | 
|  | } | 
|  |  | 
|  | void onDrawContent(SkCanvas* canvas) override { | 
|  | fScene->render(canvas); | 
|  | } | 
|  |  | 
|  | Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override { | 
|  | if (auto node = fScene->nodeAt({x, y})) { | 
|  | Click* click = new Click(this); | 
|  | click->fMeta.setPtr("node", (void*)node); | 
|  | return click; | 
|  | } | 
|  | return this->INHERITED::onFindClickHandler(x, y, modi); | 
|  | } | 
|  |  | 
|  | bool onClick(Click* click) override { | 
|  | sksg::Draw* node = nullptr; | 
|  | if (click->fMeta.findPtr("node", (void**)&node)) { | 
|  | if (auto info = this->findInfo(node)) { | 
|  | auto geo = info->fGeo; | 
|  | sksg::Rect* r = (sksg::Rect*)geo; | 
|  | SkScalar dx = click->fCurr.fX - click->fPrev.fX; | 
|  | SkScalar dy = click->fCurr.fY - click->fPrev.fY; | 
|  | r->setL(r->getL() + dx); | 
|  | r->setR(r->getR() + dx); | 
|  | r->setT(r->getT() + dy); | 
|  | r->setB(r->getB() + dy); | 
|  | } | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | private: | 
|  |  | 
|  | typedef Sample INHERITED; | 
|  | }; | 
|  |  | 
|  | ////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | DEF_SAMPLE( return new SampleSG(); ) |