マメな人はバカであれ

バカなりに考えて、バカなりに行動します

技術的なことや、趣味的なことや、私生活的なことを書いてきます

PlayCanvasのhtmlファイルなどをローカルのテキストエディタからuploadする [REST API]

Qiitaでも投稿しているものをこちらでも同じ内容で投稿しました。

qiita.com

注意:このREST APIを使用するには有料のORGANIZATIONプランに加入する必要があります(2019/06/07現在)
全プランでZIPをダウンロードすることができるようになりました。(2020/07/10〜)

PlayCanvas

GLSLやらwebGLやらをよくみるようになってから勉強するようになったんですが、
如何せん理解するのが難しいこの頃です。

もっと簡単にwebGLとか触れないかなと探して見つけたのが、PlayCanvasでした。
Unityみたいなエディター画面ですが、この画面からwebGLのコンテンツを作れるようで。すごいなー…

Flashが完全廃止され、HTML5ゲームとかが出てきている最中、こんなツール?が出てきたら開発の時間のコストも下がりそうですね。
そんな私はゲームは作ったことがないですが…これを機に作ってみたいですね。

ちなみにPlayCanvasはクラウドのサービスで、その中にコードエディターもあるのですが…
今まで使っていたコードエディターと比べるとsnippetが入っていないだけで結構打ちづらくなりまして…なんとか出来ないかなあ。

そこで、REST APIを使ってローカルのエディターからPlayCanvasのクラウド上になんとかuplaod出来ないかなと。

gulp-playcanvasなるREST APIの必要な情報を入れるだけでuploadが出来ちゃうものがありました。ステキ。
早速中身を見てみましょう!!

gulp-playcanvas

読んでみる

https://github.com/yushimatenjin/gulp-playcanvas

これを読んでみる。
(上記githubのreadmeから以下のコードを引用 ※2019/06/07現在)

npmでインストールして

npm i -D gulp-playcanvas

config.jsに必要な情報を入れて

//config.js
module.exports = {
  accessToken: "accessToken",
  scenes: [scene],
  projectId: projectId,
  branchId: "branchId", 
  projectName: "projectName", 
  remotePath: "remotePath" //PlayCanvasエディター上で配置したフォルダ (例, dev, web...)
};

gulpfile.jsに設置…

//gulpfile.js
const gulp = require("gulp");
const playcanvas = require("gulp-playcanvas");
const pcOptions = require("./config");
const pug = require("gulp-pug");
const sass = require("gulp-sass");

gulp.task("pug", () => {
  return gulp
    .src(["src/**/*.pug", "!src/**/_*.pug"])
    .pipe(pug())
    .pipe(gulp.dest("dist/"))
    .pipe(playcanvas(pcOptions));
});

gulp.task("js", () => {
  return gulp
    .src(["src/**/*.js", "!src/**/_*.js"])
    .pipe(gulp.dest("dist/"))
    .pipe(playcanvas(pcOptions));
});

gulp.task("sass", () => {
  return gulp
    .src("src/**/*.+(scss|sass)")
    .pipe(sass())
    .pipe(gulp.dest("dist/"))
    .pipe(playcanvas(pcOptions));
});

gulp.task("watch", function() {
  gulp.watch(["src/**/*.pug", "!src/**/_*.pug"], gulp.task("pug"));
  gulp.watch(["src/**/*.js", "!src/**/_*.js"], gulp.task("js"));
  gulp.watch("src/**/*.+(scss|sass)", gulp.task("sass"));
});
gulp.task("default", gulp.parallel("watch"));

pugとsassとjsを更新するたびにplaycanvas(pcOptions)でuploadするようですね。

早速自分のgulp環境でもやってみよう!


自分のgulpfile.js

ちょっと突貫で作ったので結構汚いのですが許して…

const gulp = require("gulp");
const pug = require("gulp-pug");
const sass = require("gulp-sass");
const postcss = require("gulp-postcss");
const autoprefixer = require("autoprefixer");
const cache = require("gulp-cache");
const terser = require("gulp-terser");
const rename = require("gulp-rename");
const notify = require("gulp-notify");
const changed = require("gulp-changed");
const plumber = require("gulp-plumber");

const browserSync = require("browser-sync");
const runSequence = require("run-sequence");

const playcanvas = require("gulp-playcanvas");
const pcOptions = require("./config");


const sassOptions = {
outputStyle: "expanded",
sourceMap: true,
sourceComments: false
};

const autoprefixerOptions = {
browsers: ["last 2 version", "ie >= 11", "Android >= 4.0"]
};

gulp.task('clear', function (done) {
  return cache.clearAll(done);
});

gulp.task("pug", () => {
  return gulp
    .src(["src/pug/**/*.pug", "!src/pug/**/_*.pug"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(pug({
      pretty: true,
      locals: {
        playcanvas: false
      }
    }))
    .pipe(changed("dist", {extension: '.html'}))
    .pipe(gulp.dest("dist/"))
    .pipe(browserSync.stream())
});
gulp.task("pug2", () => {
  return gulp
    .src(["src/pug/**/*.pug", "!src/pug/**/_*.pug"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(pug({
      pretty: true,
      locals: {
        playcanvas: false
      }
    }))
    .pipe(gulp.dest("dist/"))
    .pipe(browserSync.stream())
});
gulp.task("pug_pc", () => {
  return gulp
    .src(["src/pug/**/*.pug", "!src/pug/**/_*.pug"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(pug({
      pretty: true,
      locals: {
        playcanvas: true
      }
    }))
    .pipe(changed("pc", {extension: '.html'}))
    .pipe(gulp.dest("pc/"))
    .pipe(playcanvas(pcOptions));
});
gulp.task("pug2_pc", () => {
  return gulp
    .src(["src/pug/**/*.pug", "!src/pug/**/_*.pug"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(pug({
      pretty: true,
      locals: {
        playcanvas: true
      }
    }))
    .pipe(gulp.dest("pc/"))
    .pipe(playcanvas(pcOptions));
});



gulp.task("js", () => {
  return gulp
    .src(["src/js/*.js", "!src/js/_*.js"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(terser())
    .pipe(rename({extname: ".min.js"}))
    .pipe(gulp.dest("dist/js"))
    .pipe(browserSync.stream())
    .pipe(gulp.dest("pc/"))
    .pipe(playcanvas(pcOptions));
});

gulp.task("sass", () => {
  return gulp
    .src("src/sass/*.+(scss|sass)")
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(sass(sassOptions))
    .pipe(postcss([autoprefixer({autoprefixerOptions})]))
    .pipe(gulp.dest("dist/css"))
    .pipe(browserSync.stream())
    .pipe(sass({outputStyle: "compressed"}))
    .pipe(gulp.dest("pc/"))
    .pipe(playcanvas(pcOptions));
});

gulp.task("browser-sync", () => {
  browserSync.init({
    online: true,
    ui: false,
        server: {
            baseDir: "./dist",
        },
    port: 1234
  });
});
//監視開始
gulp.task("watch", () => {
  gulp.watch(['src/pug/**/*.pug','!src/pug/**/_*.pug'], gulp.task("pug"));
  gulp.watch(['src/pug/**/_*.pug'], gulp.task("pug2"));
  gulp.watch("src/sass/**/*.+(scss|sass)", gulp.task("sass"));
  gulp.watch(["src/js/*.js","!src/js/*.min.js"],gulp.task("js"));

  gulp.watch(['src/pug/**/*.pug','!src/pug/**/_*.pug'], gulp.task("pug_pc"));
  gulp.watch(['src/pug/**/_*.pug'], gulp.task("pug2_pc"));
});

gulp.task('default', gulp.parallel('clear', 'watch', "browser-sync"));

多分綺麗な書き方ではないのかもしれないですが、自分の環境に入れられました!

変数

const playcanvas = require("gulp-playcanvas");
const pcOptions = require("./config");

requireでREST APIの情報のあるconfig.jsも一緒に持ってて、

コンパイル

gulp.task("pug_pc", () => {
  return gulp
    .src(["src/pug/**/*.pug", "!src/pug/**/_*.pug"])
    .pipe(plumber({errorHandler: notify.onError('<%= error.message %>')}))
    .pipe(pug({
      pretty: true,
      locals: {
        playcanvas: true
      }
    }))
    .pipe(changed("pc", {extension: '.html'}))
    .pipe(gulp.dest("pc/"))
    .pipe(playcanvas(pcOptions));

コンパイル後のデータをplaycanvas(pcOptions))REST APIを叩きuploadします。

ディレクトリを区分

ローカルではbrowser-syncで確認したいファイルとuploadするファイルとで区別したかったのでgulp.taskを増やしています。
(もっと綺麗な書き方があったら教えてください…)

/*-- ローカルで確認するディレクトリ --*/
.pipe(gulp.dest("dist/"))
/*-- PlayCanvasへuploadするディレクトリ --*/
.pipe(gulp.dest("pc/"))

htmlのheadタグなどPlayCanvasでは不要な要素

PlayCanvasでhtmlファイルを使い時に、<html>とか<head>とかいらないタグが出てきまして。
これを捨てるためにgulpからpugに変数を送っています。

    .pipe(pug({
      locals: {
        playcanvas: true
      }
    }))

playcanvasという変数でtrue/falseを取り、pugファイル内でifを使って区分けしていきます。

- if(!playcanvas) {
    doctype html
    html(lang='ja')
- }
    - if(!playcanvas) {
        head(prefix='og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#')
            meta(charset='utf-8')
            title #{_title_str}
            meta(http-equiv='X-UA-Compatible', content='IE=edge')
            meta(name='description', content='_desc_str')
            meta(name='keywords', content='_keys_str')
            meta(name='viewport', content='width=device-width,user-scalable=yes')
            link(rel='stylesheet', href=DIR_CSS + 'master.css')
            block link
    - }
    - if(!playcanvas) {
        body
    - }
        .wrapper
            main.main
                .container
                    block body
    - if(!playcanvas) {
        //- 全体共通のjs
        script(src= DIR_JS + 'libs.min.js')
        script(src= DIR_JS + 'functions.min.js')
        block script
    - }

動いた!

そんなこんなで動きました!
更新したら以下の画像のファイルたちがplaycanvasのアセットとしてuploadされていました〜

スクリーンショット 2019-06-07 16.02.41.png スクリーンショット 2019-06-07 16.04.00.png

更新するたびにREST APIが叩かれるので連打することがなければ問題なく使えそうです。
ただ、PlayCanvasにはディレクトリを作成するREST APIが無いようで…
そのため、今回uploadするためのディレクト/pcコンパイルされるファイルたちは階層を保持しないようにする必要があります。
また、uploadする先のPlayCanvasのディレクトリも階層を持たないroot直下のディレクトリに限られるそうです。

このREST APIを使ったやり方もパワープレイではありますが、おかげで開発が前より捗るようになりました。
もっと綺麗な書き方ややり方があるとは思いますが、とりあえずはこれ…

今回のこのプロジェクトファイルと使用したい人がいたらgithubにあげているので確認してみてください。
このまま使用しても多分sassやらpugやら消し忘れているコードがあったりしてエラーが出るので、自分なりに書き換えて使用するよう注意してください。
https://github.com/sutobu000/playcanvas-codingSet


参考・引用