├── .firebaserc ├── .gitignore ├── FUNDING.yml ├── LICENSE ├── README.md ├── favicon.png ├── favicon2.png ├── firebase.json ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.cjs ├── public ├── comics │ └── aiai61555228 │ │ ├── intro1.jpg │ │ ├── intro2.jpg │ │ └── intro3.jpg ├── fonts │ ├── GenEiAntiqueNv5-M.woff2 │ ├── GenEiLateGoN_v2.woff2 │ ├── GenEiLateMinN_v2.woff2 │ ├── GenEiMGothic2-Black.woff2 │ ├── GenEiPOPle-Bk.woff2 │ ├── HuiFont29.woff2 │ └── MakibaFont13.woff2 ├── postingGuideline.html ├── privacy.html ├── termsOfService.html └── transfer │ ├── mangafarm.webp │ └── mangafarm.webp:Zone.Identifier ├── src ├── App.svelte ├── Footer.svelte ├── about │ ├── About.svelte │ ├── StructureTree.svelte │ ├── aboutStore.ts │ └── structureTreeStore.ts ├── app.postcss ├── assets │ ├── about.png │ ├── ads-leave.png │ ├── aipictors_logo_0.png │ ├── angle.png │ ├── barricade.png │ ├── bell.png │ ├── binoculars.png │ ├── bubbleLayer │ │ ├── bubble-drop.png │ │ ├── bubble-lock.png │ │ ├── bubble-offset.png │ │ ├── bubble-rotate.png │ │ ├── bubble-scale.png │ │ ├── bubble-unlock.png │ │ ├── bubble-zminus.png │ │ ├── bubble-zplus.png │ │ ├── bubble.png │ │ ├── circle.png │ │ ├── drag.png │ │ ├── radius.png │ │ ├── remove.png │ │ ├── tail-mid.png │ │ ├── tail-tip.png │ │ └── unite.png │ ├── cabinet.png │ ├── clipboard.png │ ├── download.png │ ├── drop.png │ ├── dump-restore.png │ ├── embedded.png │ ├── farm │ │ └── private.png │ ├── feathral.png │ ├── file-manager.png │ ├── fileManager │ │ ├── file.png │ │ ├── folder.png │ │ ├── new-file.png │ │ ├── new-folder.png │ │ ├── package-export.png │ │ ├── package-import.png │ │ ├── pagename-mode.png │ │ ├── paste.png │ │ ├── rename.png │ │ └── trash.png │ ├── filmlist │ │ ├── delete.png │ │ ├── effect.png │ │ ├── eye.png │ │ ├── generate.png │ │ ├── outpainting.png │ │ ├── punch.png │ │ ├── scribble.png │ │ └── trash.png │ ├── fonts │ │ └── labels │ │ │ ├── BIZ-UDGothic.png │ │ │ ├── BIZ-UDMincho.png │ │ │ ├── BIZ-UDPGothic.png │ │ │ ├── BIZ-UDPMincho.png │ │ │ ├── Cherry-Bomb-One.png │ │ │ ├── Darumadrop-One.png │ │ │ ├── Dela-Gothic-One.png │ │ │ ├── DotGothic16.png │ │ │ ├── Hachi-Maru-Pop.png │ │ │ ├── Hina-Mincho.png │ │ │ ├── IBM-Plex-Sans-JP.png │ │ │ ├── Kaisei-Decol.png │ │ │ ├── Kaisei-HarunoUmi.png │ │ │ ├── Kaisei-Opti.png │ │ │ ├── Kaisei-Tokumin.png │ │ │ ├── Kiwi-Maru.png │ │ │ ├── Klee-One.png │ │ │ ├── Kosugi-Maru.png │ │ │ ├── Kosugi.png │ │ │ ├── M-PLUS-1-Code.png │ │ │ ├── M-PLUS-1.png │ │ │ ├── M-PLUS-1p.png │ │ │ ├── M-PLUS-2.png │ │ │ ├── M-PLUS-Rounded-1c.png │ │ │ ├── Mochiy-Pop-One.png │ │ │ ├── Mochiy-Pop-P-One.png │ │ │ ├── New-Tegomin.png │ │ │ ├── Noto-Sans-JP.png │ │ │ ├── Noto-Serif-JP.png │ │ │ ├── Potta-One.png │ │ │ ├── Rampart-One.png │ │ │ ├── Reggae-One.png │ │ │ ├── RocknRoll-One.png │ │ │ ├── Sawarabi-Gothic.png │ │ │ ├── Shippori-Antique-B1.png │ │ │ ├── Shippori-Antique.png │ │ │ ├── Shippori-Mincho-B1.png │ │ │ ├── Shippori-Mincho.png │ │ │ ├── Shizuru.png │ │ │ ├── Slackside-One.png │ │ │ ├── Stick.png │ │ │ ├── Yomogi.png │ │ │ ├── Yuji-Boku.png │ │ │ ├── Yuji-Mai.png │ │ │ ├── Yuji-Syuku.png │ │ │ ├── Yusei-Magic.png │ │ │ ├── Zen-Antique-Soft.png │ │ │ ├── Zen-Antique.png │ │ │ ├── Zen-Kaku-Gothic-Antique.png │ │ │ ├── Zen-Kaku-Gothic-New.png │ │ │ ├── Zen-Kurenaido.png │ │ │ ├── Zen-Maru-Gothic.png │ │ │ ├── Zen-Old-Mincho.png │ │ │ ├── ふい字.png │ │ │ ├── まきばフォント.png │ │ │ ├── 源暎ぽっぷる.png │ │ │ ├── 源暎アンチック.png │ │ │ ├── 源暎エムゴ.png │ │ │ ├── 源暎ラテゴ.png │ │ │ └── 源暎ラテミン.png │ ├── frameInspector │ │ └── coffee-machine-12-64.png │ ├── frameLayer │ │ ├── decrement.png │ │ ├── delete.png │ │ ├── duplicate.png │ │ ├── expand-horizontal.png │ │ ├── expand-vertical.png │ │ ├── fit.png │ │ ├── flip-horizontal.png │ │ ├── flip-vertical.png │ │ ├── increment.png │ │ ├── insert-horizontal.png │ │ ├── insert-vertical.png │ │ ├── reset-padding.png │ │ ├── rotate.png │ │ ├── scale.png │ │ ├── shift.png │ │ ├── slant-horizontal.png │ │ ├── slant-vertical.png │ │ ├── split-horizontal.png │ │ ├── split-vertical.png │ │ ├── swap.png │ │ ├── unshift.png │ │ ├── visibility1.png │ │ ├── visibility2.png │ │ ├── visibility3.png │ │ ├── zminus.png │ │ └── zplus.png │ ├── generate-image.png │ ├── get-old.png │ ├── get.png │ ├── horizontal.png │ ├── json.png │ ├── movie.png │ ├── new-book.png │ ├── new-page.png │ ├── page-bubbles.png │ ├── page-clipboard.png │ ├── page-cut-vertical.png │ ├── page-cut.png │ ├── page-imaging.png │ ├── page-insert-vertical.png │ ├── page-insert.png │ ├── page-mark-on.png │ ├── page-mark.png │ ├── page-paste.png │ ├── page-trash.png │ ├── page-tweak.png │ ├── pin-white.png │ ├── pin.png │ ├── redo.png │ ├── reference-selected.png │ ├── reference.png │ ├── reset.png │ ├── ruler.png │ ├── stamp.png │ ├── svelte.svg │ ├── telescope.png │ ├── title-bubble.png │ ├── title-control-panel.png │ ├── transparent.png │ ├── trash.png │ ├── undo.png │ ├── unembedded.png │ ├── vertical.png │ ├── video.png │ ├── videomaker │ │ ├── pause.png │ │ └── play.png │ ├── viewer │ │ ├── left.png │ │ └── right.png │ └── write.png ├── bookeditor │ ├── BookEditor.svelte │ ├── FontLoader.svelte │ ├── TemplateChooser.svelte │ ├── TemplateSample.svelte │ ├── bookEditorUtils.ts │ ├── bookStore.ts │ ├── bubbleinspector │ │ ├── BubbleInspector.svelte │ │ ├── BubbleInspectorAppendix.svelte │ │ ├── BubbleSample.svelte │ │ ├── BubbleTemplateSample.svelte │ │ ├── FontChooser.svelte │ │ ├── HistoryStorage.svelte │ │ ├── ShapeChooser.svelte │ │ ├── WebFontList.svelte │ │ ├── WebFontListItem.svelte │ │ ├── bubbleInspectorStore.ts │ │ ├── fontStore.ts │ │ └── shapeStore.ts │ ├── effectchooser │ │ ├── EffectChooser.svelte │ │ └── effectChooserStore.ts │ ├── frameinspector │ │ ├── FilmEffect.svelte │ │ ├── FilmList.svelte │ │ ├── FilmListItem.svelte │ │ ├── FrameInspector.svelte │ │ └── frameInspectorStore.ts │ ├── pageinspector │ │ ├── PageInspector.svelte │ │ └── pageInspectorStore.ts │ └── templateChooserStore.ts ├── box.css ├── bubbleBucket │ ├── BubbleBucket.svelte │ ├── BubbleBucketItem.svelte │ └── bubbleBucketStore.ts ├── controlpanel │ ├── ControlPanel.svelte │ └── controlPanelStore.ts ├── customTypes.d.ts ├── downloader │ ├── Downloader.svelte │ └── downloaderStore.ts ├── filemanager │ ├── FileManager.svelte │ ├── FileManagerFile.svelte │ ├── FileManagerFolder.svelte │ ├── FileManagerFolderTail.svelte │ ├── FileManagerInsertZone.svelte │ ├── FileManagerRoot.svelte │ ├── currentFile.ts │ ├── developmentFileSystem.ts │ ├── fileImages.ts │ ├── fileManagerStore.ts │ ├── productionFileSystem.ts │ ├── shareFileSystem.ts │ ├── specialFolders.ts │ └── test │ │ ├── filesystem.correct.typeA.json │ │ ├── filesystem.correct.typeB.json │ │ ├── filesystem.correct.typeC.json │ │ ├── filesystem.initial.json │ │ └── garbagecollection.vitest.ts ├── firebase.ts ├── generator │ ├── BatchImaging.svelte │ ├── BatchImagingDalle3.svelte │ ├── BatchImagingFeathral.svelte │ ├── BatchImagingFlux.svelte │ ├── FluxModes.svelte │ ├── Gallery.svelte │ ├── GalleryImage.svelte │ ├── ImageGenerator.svelte │ ├── ImageGeneratorDalle3.svelte │ ├── ImageGeneratorFeathral.svelte │ ├── ImageGeneratorFlux.svelte │ ├── ImageGeneratorPlain.svelte │ ├── ImageGeneratorStableDiffusion.svelte │ ├── ImageProvider.svelte │ ├── ImagingProgressBar.svelte │ ├── batchImagingStore.ts │ ├── imageGeneratorStore.ts │ └── sdwebui.ts ├── lib │ ├── book.test.ts │ ├── book │ │ ├── book.ts │ │ ├── envelope.ts │ │ ├── imagePacking.ts │ │ ├── layout.ts │ │ ├── notebook.ts │ │ ├── richChat.ts │ │ └── storyboard.ts │ ├── filesystem │ │ ├── contentStorage │ │ │ ├── backblazeImageStorage.ts │ │ │ ├── contentStorage.ts │ │ │ └── firebaseImageStorage.ts │ │ ├── fileSystem.ts │ │ ├── firebaseFileSystem.ts │ │ ├── indexeddbFileSystem.ts │ │ └── mockFileSystem.ts │ ├── layeredCanvas │ │ ├── dataModels │ │ │ ├── bubble.ts │ │ │ ├── effect.ts │ │ │ ├── film.ts │ │ │ ├── frameTree.ts │ │ │ └── media.ts │ │ ├── layers │ │ │ ├── SampleLayer.ts │ │ │ ├── arrayLayer.ts │ │ │ ├── bubbleLayer.ts │ │ │ ├── floorLayer.ts │ │ │ ├── frameLayer.ts │ │ │ ├── inlinePainterLayer.ts │ │ │ ├── paperRendererLayer.ts │ │ │ └── undoLayer.ts │ │ ├── system │ │ │ ├── keyCache.ts │ │ │ ├── layeredCanvas.ts │ │ │ └── paperArray.ts │ │ └── tools │ │ │ ├── draw │ │ │ ├── bubbleGraphic.ts │ │ │ ├── clickableIcon.ts │ │ │ ├── drawFilmStack.ts │ │ │ ├── drawText.ts │ │ │ ├── richText.ts │ │ │ ├── selectionFrame.ts │ │ │ ├── typeSetting.ts │ │ │ └── verticalText.ts │ │ │ ├── focusKeeper.ts │ │ │ ├── frameExamples.ts │ │ │ ├── geometry │ │ │ ├── bubbleGeometry.ts │ │ │ ├── convertPoint.ts │ │ │ ├── geometry.ts │ │ │ ├── geometry.vitest.ts │ │ │ ├── quickHull.ts │ │ │ └── trapezoid.ts │ │ │ ├── grid.ts │ │ │ ├── haiku.ts │ │ │ ├── imageUtil.ts │ │ │ ├── kinsoku.ts │ │ │ ├── kinsoku.vitest.js │ │ │ ├── misc.ts │ │ │ ├── paper.d.ts │ │ │ ├── perfectFreehandUtil.ts │ │ │ ├── pictureControl.ts │ │ │ └── rectHandle.ts │ └── sample.test.ts ├── main.ts ├── mangaview │ ├── MangaView.svelte │ └── PublicationInfo.svelte ├── mascot │ ├── InlineDocument.svelte │ ├── Mascot.svelte │ ├── MascotController.ts │ ├── MascotStatus.svelte │ ├── MascotTimeline.svelte │ ├── mascotStore.ts │ ├── servant.ts │ ├── servantContext.ts │ ├── storyboard.ts │ └── storyboardServant.ts ├── materialBucket │ ├── MaterialBucket.svelte │ └── materialBucketStore.ts ├── notebook │ ├── AutoSizeTextarea.svelte │ ├── Notebook.svelte │ ├── NotebookCharacter.svelte │ ├── NotebookCharacterList.svelte │ ├── NotebookManual.svelte │ ├── NotebookTextarea.svelte │ ├── callAdvise.ts │ ├── makePage.ts │ └── notebookStore.ts ├── painter │ ├── FreehandInspector.svelte │ ├── FreehandInspectorEasing.svelte │ ├── FreehandInspectorPalette.svelte │ ├── FreehandInspectorTaper.svelte │ ├── Painter.svelte │ └── easing.ts ├── preferences.ts ├── publication │ ├── Publication.svelte │ └── SocialCard.svelte ├── rootelements │ ├── AboutButton.svelte │ ├── BaseRootButton.svelte │ ├── BellButton.svelte │ ├── CabinetButton.svelte │ ├── DownloadButton.svelte │ ├── MaterialBucketButton.svelte │ ├── NewBookButton.svelte │ ├── RulerButton.svelte │ ├── SaveOffButton.svelte │ └── VideoButton.svelte ├── t.json ├── toolbar │ ├── AvatarIcon.svelte │ ├── ToolBar.svelte │ └── UserProfile.svelte ├── transfer │ ├── Dump.svelte │ ├── MangaFarmDialog.svelte │ └── Undump.svelte ├── uiStore.ts ├── undoStore.ts ├── utils │ ├── AutoSizeCanvas.svelte │ ├── BookArchiver.svelte │ ├── Comic.svelte │ ├── DebugOnly.svelte │ ├── Drawer.svelte │ ├── EmbeddedHtml.svelte │ ├── ExponentialRangeSlider.svelte │ ├── Feathral.svelte │ ├── FeathralCost.svelte │ ├── FileBrowser.svelte │ ├── FullScreenLoading.svelte │ ├── FullScreenProgress.svelte │ ├── ImageViewer.svelte │ ├── JsonReader.svelte │ ├── License.svelte │ ├── Loading.svelte │ ├── NumberEdit.svelte │ ├── Parameter.svelte │ ├── PassiveToolTip.svelte │ ├── Progress.svelte │ ├── RenameEdit.svelte │ ├── SignIn.svelte │ ├── SliderEdit.svelte │ ├── SpreadCanvas.svelte │ ├── Spreader.svelte │ ├── TreeView.svelte │ ├── accountStore.ts │ ├── ads │ │ ├── AdContainer.svelte │ │ └── AdPanel.svelte │ ├── analyzeImage.ts │ ├── asyncStore.ts │ ├── backUpIndexedDB.ts │ ├── bookArchiverStore.ts │ ├── colorpicker │ │ ├── ColorPickerDialog.svelte │ │ ├── ColorPickerLabel.svelte │ │ └── colorPickerStore.ts │ ├── delayedCommiter.ts │ ├── developmentFlagStore.ts │ ├── dropzone.ts │ ├── effectprocessor │ │ └── effectProcessorStore.ts │ ├── executeProcessAndNotify.ts │ ├── feathralImaging.ts │ ├── fileBrowserStore.ts │ ├── fileDroppableList.ts │ ├── fromHiruma.ts │ ├── garbageCollection.ts │ ├── harmony.ts │ ├── hiruma.ts │ ├── hoverKeyStore.ts │ ├── imageViewerStore.ts │ ├── loadingStore.ts │ ├── moveInArray.ts │ ├── observeResize.ts │ ├── observeWithin.ts │ ├── outPaintFilm.ts │ ├── passiveToolTipStore.ts │ ├── persistentText.ts │ ├── pubsub.ts │ ├── punchFilm.ts │ ├── reactUtil.ts │ ├── rmbg.ts │ ├── saver │ │ ├── copyToClipboard.ts │ │ ├── exportPrompts.ts │ │ ├── postToAiPictors.ts │ │ ├── renderPage.ts │ │ ├── saveAsPng.ts │ │ ├── saveAsPsd.ts │ │ └── saveAsZip.ts │ ├── selection.ts │ ├── shineEffect.ts │ ├── sortableList.ts │ └── waitDialog.ts ├── videomaker │ ├── FrameResidenceTime.svelte │ ├── SeekBar.svelte │ ├── VideoMaker.svelte │ ├── VideoPlayer.svelte │ ├── buildProgram.ts │ ├── generateMovieFile.ts │ ├── generateScenes.ts │ └── renderProgram.ts ├── vite-env.d.ts └── weaver │ └── storyboard.ts ├── svelte.config.js ├── tailwind.config.cjs ├── test └── setup.ts ├── tsconfig.json ├── tsconfig.node.json ├── tsconfig.svelte-check.json ├── viewer.html └── vite.config.ts /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "frameplanner-e5569" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | public/ads 15 | .firebase/* 16 | junk/* 17 | public/stamp.txt 18 | .editorconfig 19 | # アーカイバ 20 | md-archiver 21 | # アーカイブファイル 22 | archive.md 23 | # バナー広告 24 | public/banners/* 25 | # npmのサイズとか出すやつ 26 | stats.html 27 | # ダンプ用の巨大なテストデータ 28 | testdata/* 29 | 30 | # Editor directories and files 31 | .vscode/* 32 | .idea 33 | .DS_Store 34 | *.suo 35 | *.ntvs* 36 | *.njsproj 37 | *.sln 38 | *.sw? 39 | -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: ["jonigata"] 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Naoyuki Hirayama 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FramePlanner 2 | 3 | マンガの枠組みをツリー構造のデータ(JSON)で定義して、その中で各コマをウィンドウのように扱って絵を配置できるツールです。 4 | 5 | 現在「[まんがファーム](https://manga-farm.online/)」の1セクションとなっています。まんがファームにリリースされているのはsns_mainブランチです。 6 | 7 | ## 操作・機能 8 | 9 | https://user-images.githubusercontent.com/128374/227374915-7b2a48c0-270c-411e-b584-427322663537.mp4 10 | 11 | https://user-images.githubusercontent.com/128374/227375161-c7eb2511-1c06-4746-8ee6-7eec095deb06.mp4 12 | 13 | https://user-images.githubusercontent.com/128374/227375169-74fbdb1f-0aa0-4926-94f9-4674b680e473.mp4 14 | 15 | ## インストール方法 16 | 17 | 以下の手順に従って、FramePlanner2をインストールして開発サーバーを起動します。 18 | (WSL2、ubuntu22前提) 19 | 20 | 1.このリポジトリをクローン: 21 | ```bash 22 | git clone https://github.com/jonigata/FramePlanner2.git 23 | ``` 24 | 2.ディレクトリに移動: 25 | ```bash 26 | cd FramePlanner2 27 | ``` 28 | 3.必要な依存関係をインストール: 29 | ```bash 30 | npm install 31 | ``` 32 | 4.開発サーバーを起動: 33 | ```bash 34 | npm run dev 35 | ``` 36 | 5.ブラウザでアプリケーションにアクセス: 37 | ``` 38 | http://localhost:5173 39 | ``` 40 | 41 | ## フキダシの追加方法 42 | 43 | 1. src/lib/layeredCanvas/bubbleGraphic.jsに関数を追加 44 | 2. src/lib/layeredCanvas/bubbleGraphic.jsのdrawBubbleにエントリを追加 45 | 3. src/BubbleChooser.svelteの真ん中あたりに形状が列挙してある場所があるので、そこに追加 46 | 47 | ## ライセンス 48 | MIT 49 | 50 | ユーザーが制作したコンテンツに関しては一切関知しません。 -------------------------------------------------------------------------------- /favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/favicon.png -------------------------------------------------------------------------------- /favicon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/favicon2.png -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "/viewer/:envelope", 12 | "destination": "/viewer.html" 13 | }, 14 | { 15 | "source": "**", 16 | "destination": "/index.html" 17 | } 18 | ], 19 | "headers": [ 20 | { 21 | "source": "**/*.@(jpg|jpeg|gif|png|svg|webp|woff2)", 22 | "headers": [ 23 | { 24 | "key": "Cache-Control", 25 | "value": "public, max-age=31536000, immutable" 26 | } 27 | ] 28 | } 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | FramePlanner 13 | 14 | 15 |
16 |

まんがファーム

17 |

18 | まんがファームは、AIで漫画を作って共有できる新しいSNSです。 19 |

20 |
21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | const tailwindcss = require("tailwindcss"); 2 | const autoprefixer = require("autoprefixer"); 3 | 4 | const config = { 5 | plugins: [ 6 | //Some plugins, like tailwindcss/nesting, need to run before Tailwind, 7 | tailwindcss(), 8 | //But others, like autoprefixer, need to run after, 9 | autoprefixer, 10 | ], 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /public/comics/aiai61555228/intro1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/comics/aiai61555228/intro1.jpg -------------------------------------------------------------------------------- /public/comics/aiai61555228/intro2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/comics/aiai61555228/intro2.jpg -------------------------------------------------------------------------------- /public/comics/aiai61555228/intro3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/comics/aiai61555228/intro3.jpg -------------------------------------------------------------------------------- /public/fonts/GenEiAntiqueNv5-M.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/GenEiAntiqueNv5-M.woff2 -------------------------------------------------------------------------------- /public/fonts/GenEiLateGoN_v2.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/GenEiLateGoN_v2.woff2 -------------------------------------------------------------------------------- /public/fonts/GenEiLateMinN_v2.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/GenEiLateMinN_v2.woff2 -------------------------------------------------------------------------------- /public/fonts/GenEiMGothic2-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/GenEiMGothic2-Black.woff2 -------------------------------------------------------------------------------- /public/fonts/GenEiPOPle-Bk.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/GenEiPOPle-Bk.woff2 -------------------------------------------------------------------------------- /public/fonts/HuiFont29.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/HuiFont29.woff2 -------------------------------------------------------------------------------- /public/fonts/MakibaFont13.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/fonts/MakibaFont13.woff2 -------------------------------------------------------------------------------- /public/transfer/mangafarm.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/transfer/mangafarm.webp -------------------------------------------------------------------------------- /public/transfer/mangafarm.webp:Zone.Identifier: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/public/transfer/mangafarm.webp:Zone.Identifier -------------------------------------------------------------------------------- /src/about/aboutStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const aboutOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/about/structureTreeStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const structureTreeOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/app.postcss: -------------------------------------------------------------------------------- 1 | /* Write your global styles here, in PostCSS syntax */ 2 | 3 | :root { 4 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 5 | line-height: 1.5; 6 | font-weight: 400; 7 | 8 | color-scheme: light dark; 9 | color: rgba(255, 255, 255, 0.87); 10 | background-color: #242424; 11 | 12 | font-synthesis: none; 13 | text-rendering: optimizeLegibility; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-text-size-adjust: 100%; 17 | } 18 | 19 | a { 20 | font-weight: 500; 21 | color: #646cff; 22 | text-decoration: inherit; 23 | } 24 | a:hover { 25 | color: #535bf2; 26 | } 27 | 28 | body { 29 | margin: 0; 30 | display: flex; 31 | place-items: center; 32 | min-width: 320px; 33 | min-height: 100vh; 34 | } 35 | 36 | h1 { 37 | font-size: 3.2em; 38 | line-height: 1.1; 39 | } 40 | 41 | .card { 42 | padding: 2em; 43 | } 44 | 45 | #app { 46 | } 47 | 48 | button { 49 | border-radius: 8px; 50 | border: 1px solid transparent; 51 | padding: 0.6em 1.2em; 52 | font-size: 1em; 53 | font-weight: 500; 54 | font-family: inherit; 55 | background-color: #1a1a1a; 56 | cursor: pointer; 57 | transition: border-color 0.25s; 58 | } 59 | button:hover { 60 | border-color: #646cff; 61 | } 62 | button:focus, 63 | button:focus-visible { 64 | outline: 4px auto -webkit-focus-ring-color; 65 | } 66 | 67 | @media (prefers-color-scheme: light) { 68 | :root { 69 | color: #213547; 70 | background-color: #ffffff; 71 | } 72 | a:hover { 73 | color: #747bff; 74 | } 75 | button { 76 | background-color: #f9f9f9; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/assets/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/about.png -------------------------------------------------------------------------------- /src/assets/ads-leave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/ads-leave.png -------------------------------------------------------------------------------- /src/assets/aipictors_logo_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/aipictors_logo_0.png -------------------------------------------------------------------------------- /src/assets/angle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/angle.png -------------------------------------------------------------------------------- /src/assets/barricade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/barricade.png -------------------------------------------------------------------------------- /src/assets/bell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bell.png -------------------------------------------------------------------------------- /src/assets/binoculars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/binoculars.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-drop.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-lock.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-offset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-offset.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-rotate.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-scale.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-unlock.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-zminus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-zminus.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble-zplus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble-zplus.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/bubble.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/circle.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/drag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/drag.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/radius.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/radius.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/remove.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/tail-mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/tail-mid.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/tail-tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/tail-tip.png -------------------------------------------------------------------------------- /src/assets/bubbleLayer/unite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/bubbleLayer/unite.png -------------------------------------------------------------------------------- /src/assets/cabinet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/cabinet.png -------------------------------------------------------------------------------- /src/assets/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/clipboard.png -------------------------------------------------------------------------------- /src/assets/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/download.png -------------------------------------------------------------------------------- /src/assets/drop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/drop.png -------------------------------------------------------------------------------- /src/assets/dump-restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/dump-restore.png -------------------------------------------------------------------------------- /src/assets/embedded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/embedded.png -------------------------------------------------------------------------------- /src/assets/farm/private.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/farm/private.png -------------------------------------------------------------------------------- /src/assets/feathral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/feathral.png -------------------------------------------------------------------------------- /src/assets/file-manager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/file-manager.png -------------------------------------------------------------------------------- /src/assets/fileManager/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/file.png -------------------------------------------------------------------------------- /src/assets/fileManager/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/folder.png -------------------------------------------------------------------------------- /src/assets/fileManager/new-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/new-file.png -------------------------------------------------------------------------------- /src/assets/fileManager/new-folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/new-folder.png -------------------------------------------------------------------------------- /src/assets/fileManager/package-export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/package-export.png -------------------------------------------------------------------------------- /src/assets/fileManager/package-import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/package-import.png -------------------------------------------------------------------------------- /src/assets/fileManager/pagename-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/pagename-mode.png -------------------------------------------------------------------------------- /src/assets/fileManager/paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/paste.png -------------------------------------------------------------------------------- /src/assets/fileManager/rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/rename.png -------------------------------------------------------------------------------- /src/assets/fileManager/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fileManager/trash.png -------------------------------------------------------------------------------- /src/assets/filmlist/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/delete.png -------------------------------------------------------------------------------- /src/assets/filmlist/effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/effect.png -------------------------------------------------------------------------------- /src/assets/filmlist/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/eye.png -------------------------------------------------------------------------------- /src/assets/filmlist/generate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/generate.png -------------------------------------------------------------------------------- /src/assets/filmlist/outpainting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/outpainting.png -------------------------------------------------------------------------------- /src/assets/filmlist/punch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/punch.png -------------------------------------------------------------------------------- /src/assets/filmlist/scribble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/scribble.png -------------------------------------------------------------------------------- /src/assets/filmlist/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/filmlist/trash.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/BIZ-UDGothic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/BIZ-UDGothic.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/BIZ-UDMincho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/BIZ-UDMincho.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/BIZ-UDPGothic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/BIZ-UDPGothic.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/BIZ-UDPMincho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/BIZ-UDPMincho.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Cherry-Bomb-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Cherry-Bomb-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Darumadrop-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Darumadrop-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Dela-Gothic-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Dela-Gothic-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/DotGothic16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/DotGothic16.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Hachi-Maru-Pop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Hachi-Maru-Pop.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Hina-Mincho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Hina-Mincho.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/IBM-Plex-Sans-JP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/IBM-Plex-Sans-JP.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kaisei-Decol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kaisei-Decol.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kaisei-HarunoUmi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kaisei-HarunoUmi.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kaisei-Opti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kaisei-Opti.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kaisei-Tokumin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kaisei-Tokumin.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kiwi-Maru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kiwi-Maru.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Klee-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Klee-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kosugi-Maru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kosugi-Maru.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Kosugi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Kosugi.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/M-PLUS-1-Code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/M-PLUS-1-Code.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/M-PLUS-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/M-PLUS-1.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/M-PLUS-1p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/M-PLUS-1p.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/M-PLUS-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/M-PLUS-2.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/M-PLUS-Rounded-1c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/M-PLUS-Rounded-1c.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Mochiy-Pop-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Mochiy-Pop-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Mochiy-Pop-P-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Mochiy-Pop-P-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/New-Tegomin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/New-Tegomin.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Noto-Sans-JP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Noto-Sans-JP.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Noto-Serif-JP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Noto-Serif-JP.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Potta-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Potta-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Rampart-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Rampart-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Reggae-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Reggae-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/RocknRoll-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/RocknRoll-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Sawarabi-Gothic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Sawarabi-Gothic.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Shippori-Antique-B1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Shippori-Antique-B1.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Shippori-Antique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Shippori-Antique.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Shippori-Mincho-B1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Shippori-Mincho-B1.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Shippori-Mincho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Shippori-Mincho.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Shizuru.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Shizuru.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Slackside-One.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Slackside-One.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Stick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Stick.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Yomogi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Yomogi.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Yuji-Boku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Yuji-Boku.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Yuji-Mai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Yuji-Mai.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Yuji-Syuku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Yuji-Syuku.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Yusei-Magic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Yusei-Magic.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Antique-Soft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Antique-Soft.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Antique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Antique.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Kaku-Gothic-Antique.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Kaku-Gothic-Antique.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Kaku-Gothic-New.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Kaku-Gothic-New.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Kurenaido.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Kurenaido.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Maru-Gothic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Maru-Gothic.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/Zen-Old-Mincho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/Zen-Old-Mincho.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/ふい字.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/ふい字.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/まきばフォント.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/まきばフォント.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/源暎ぽっぷる.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/源暎ぽっぷる.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/源暎アンチック.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/源暎アンチック.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/源暎エムゴ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/源暎エムゴ.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/源暎ラテゴ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/源暎ラテゴ.png -------------------------------------------------------------------------------- /src/assets/fonts/labels/源暎ラテミン.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/fonts/labels/源暎ラテミン.png -------------------------------------------------------------------------------- /src/assets/frameInspector/coffee-machine-12-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameInspector/coffee-machine-12-64.png -------------------------------------------------------------------------------- /src/assets/frameLayer/decrement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/decrement.png -------------------------------------------------------------------------------- /src/assets/frameLayer/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/delete.png -------------------------------------------------------------------------------- /src/assets/frameLayer/duplicate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/duplicate.png -------------------------------------------------------------------------------- /src/assets/frameLayer/expand-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/expand-horizontal.png -------------------------------------------------------------------------------- /src/assets/frameLayer/expand-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/expand-vertical.png -------------------------------------------------------------------------------- /src/assets/frameLayer/fit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/fit.png -------------------------------------------------------------------------------- /src/assets/frameLayer/flip-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/flip-horizontal.png -------------------------------------------------------------------------------- /src/assets/frameLayer/flip-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/flip-vertical.png -------------------------------------------------------------------------------- /src/assets/frameLayer/increment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/increment.png -------------------------------------------------------------------------------- /src/assets/frameLayer/insert-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/insert-horizontal.png -------------------------------------------------------------------------------- /src/assets/frameLayer/insert-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/insert-vertical.png -------------------------------------------------------------------------------- /src/assets/frameLayer/reset-padding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/reset-padding.png -------------------------------------------------------------------------------- /src/assets/frameLayer/rotate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/rotate.png -------------------------------------------------------------------------------- /src/assets/frameLayer/scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/scale.png -------------------------------------------------------------------------------- /src/assets/frameLayer/shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/shift.png -------------------------------------------------------------------------------- /src/assets/frameLayer/slant-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/slant-horizontal.png -------------------------------------------------------------------------------- /src/assets/frameLayer/slant-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/slant-vertical.png -------------------------------------------------------------------------------- /src/assets/frameLayer/split-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/split-horizontal.png -------------------------------------------------------------------------------- /src/assets/frameLayer/split-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/split-vertical.png -------------------------------------------------------------------------------- /src/assets/frameLayer/swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/swap.png -------------------------------------------------------------------------------- /src/assets/frameLayer/unshift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/unshift.png -------------------------------------------------------------------------------- /src/assets/frameLayer/visibility1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/visibility1.png -------------------------------------------------------------------------------- /src/assets/frameLayer/visibility2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/visibility2.png -------------------------------------------------------------------------------- /src/assets/frameLayer/visibility3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/visibility3.png -------------------------------------------------------------------------------- /src/assets/frameLayer/zminus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/zminus.png -------------------------------------------------------------------------------- /src/assets/frameLayer/zplus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/frameLayer/zplus.png -------------------------------------------------------------------------------- /src/assets/generate-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/generate-image.png -------------------------------------------------------------------------------- /src/assets/get-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/get-old.png -------------------------------------------------------------------------------- /src/assets/get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/get.png -------------------------------------------------------------------------------- /src/assets/horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/horizontal.png -------------------------------------------------------------------------------- /src/assets/json.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/json.png -------------------------------------------------------------------------------- /src/assets/movie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/movie.png -------------------------------------------------------------------------------- /src/assets/new-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/new-book.png -------------------------------------------------------------------------------- /src/assets/new-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/new-page.png -------------------------------------------------------------------------------- /src/assets/page-bubbles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-bubbles.png -------------------------------------------------------------------------------- /src/assets/page-clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-clipboard.png -------------------------------------------------------------------------------- /src/assets/page-cut-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-cut-vertical.png -------------------------------------------------------------------------------- /src/assets/page-cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-cut.png -------------------------------------------------------------------------------- /src/assets/page-imaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-imaging.png -------------------------------------------------------------------------------- /src/assets/page-insert-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-insert-vertical.png -------------------------------------------------------------------------------- /src/assets/page-insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-insert.png -------------------------------------------------------------------------------- /src/assets/page-mark-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-mark-on.png -------------------------------------------------------------------------------- /src/assets/page-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-mark.png -------------------------------------------------------------------------------- /src/assets/page-paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-paste.png -------------------------------------------------------------------------------- /src/assets/page-trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-trash.png -------------------------------------------------------------------------------- /src/assets/page-tweak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/page-tweak.png -------------------------------------------------------------------------------- /src/assets/pin-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/pin-white.png -------------------------------------------------------------------------------- /src/assets/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/pin.png -------------------------------------------------------------------------------- /src/assets/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/redo.png -------------------------------------------------------------------------------- /src/assets/reference-selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/reference-selected.png -------------------------------------------------------------------------------- /src/assets/reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/reference.png -------------------------------------------------------------------------------- /src/assets/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/reset.png -------------------------------------------------------------------------------- /src/assets/ruler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/ruler.png -------------------------------------------------------------------------------- /src/assets/stamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/stamp.png -------------------------------------------------------------------------------- /src/assets/svelte.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/telescope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/telescope.png -------------------------------------------------------------------------------- /src/assets/title-bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/title-bubble.png -------------------------------------------------------------------------------- /src/assets/title-control-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/title-control-panel.png -------------------------------------------------------------------------------- /src/assets/transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/transparent.png -------------------------------------------------------------------------------- /src/assets/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/trash.png -------------------------------------------------------------------------------- /src/assets/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/undo.png -------------------------------------------------------------------------------- /src/assets/unembedded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/unembedded.png -------------------------------------------------------------------------------- /src/assets/vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/vertical.png -------------------------------------------------------------------------------- /src/assets/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/video.png -------------------------------------------------------------------------------- /src/assets/videomaker/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/videomaker/pause.png -------------------------------------------------------------------------------- /src/assets/videomaker/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/videomaker/play.png -------------------------------------------------------------------------------- /src/assets/viewer/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/viewer/left.png -------------------------------------------------------------------------------- /src/assets/viewer/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/viewer/right.png -------------------------------------------------------------------------------- /src/assets/write.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/assets/write.png -------------------------------------------------------------------------------- /src/bookeditor/TemplateChooser.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
17 | 23 |
24 | {#each frameExamples as sample, index} 25 | onClick(index)}/> 26 | {/each} 27 |
28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /src/bookeditor/TemplateSample.svelte: -------------------------------------------------------------------------------- 1 | 40 | 41 |
42 | 43 |
44 | 45 | -------------------------------------------------------------------------------- /src/bookeditor/bookStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable, derived } from "svelte/store"; 2 | import type { Viewport } from "../lib/layeredCanvas/system/layeredCanvas"; 3 | import { type Book, type BookOperators, newPage } from '../lib/book/book'; 4 | import { frameExamples } from "../lib/layeredCanvas/tools/frameExamples"; 5 | import { FrameElement } from "../lib/layeredCanvas/dataModels/frameTree"; 6 | import { Bubble } from "../lib/layeredCanvas/dataModels/bubble"; 7 | 8 | export const mainBook = writable(null); 9 | export const mainPage = derived(mainBook, $mainBook => $mainBook?.pages[0]); 10 | export const viewport: Writable = writable(null); 11 | export const bookEditor: Writable = writable(null); 12 | export const redrawToken = writable(false); 13 | // redrawToken.subscribe(value => { 14 | // console.trace('redrawToken changed:', value); 15 | // }); 16 | export const undoToken: Writable<'undo' | 'redo' | null> = writable(null); 17 | export const forceFontLoadToken = writable(false); 18 | export const fontLoadToken: Writable<{family: string, weight: string}[] | null> = writable(null); 19 | 20 | export type NewPageProperty = { 21 | paperSize: [number, number], 22 | paperColor: string, 23 | frameColor: string, 24 | frameWidth: number, 25 | templateIndex: number, 26 | }; 27 | 28 | export const newPageProperty: Writable = writable({ 29 | paperSize: [840, 1188], 30 | paperColor: "#FFFFFF", 31 | frameColor: "#000000", 32 | frameWidth: 2, 33 | templateIndex: 0, 34 | }); 35 | 36 | export function insertNewPageToBook(book: Book, p: NewPageProperty, index: number) { 37 | const example = frameExamples[p.templateIndex]; 38 | const bubbles = example.bubbles.map(b => Bubble.compile(p.paperSize, b)); 39 | const page = newPage(FrameElement.compile(example.frameTree), bubbles); 40 | page.paperSize = [...p.paperSize]; 41 | page.paperColor = p.paperColor; 42 | page.frameColor = p.frameColor; 43 | page.frameWidth = p.frameWidth; 44 | book.pages.splice(index, 0, page); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/BubbleInspectorAppendix.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 | {#if $bubble != null} 22 |
23 | {#each Object.entries($bubble.optionSet) as [key, v], _ (key)} 24 | {@const value = getAny(v)} 25 | {#if value["type"] === "number"} 26 |
27 |
{value["label"]}
28 | 34 |
35 | 36 |
37 |
38 | {/if} 39 | {#if value["type"] === "boolean"} 40 |
41 |
{value["label"]}
42 | 43 |
44 | {/if} 45 | {/each} 46 |
47 | {/if} 48 | 49 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/HistoryStorage.svelte: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/WebFontListItem.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | 27 | 28 | {font.family} 29 |
30 | 31 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/bubbleInspectorStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | import type { Bubble } from "../../lib/layeredCanvas/dataModels/bubble"; 3 | import type { Film } from "../../lib/layeredCanvas/dataModels/film"; 4 | import type { Page } from '../../lib/book/book'; 5 | 6 | type BubbleInspectorCommand = "generate" | "scribble" | "punch"; 7 | 8 | export type BubbleInspectorPosition = { 9 | center: {x: number, y: number}, 10 | height: number, 11 | offset: number, 12 | } 13 | 14 | export type BubbleInspectorTarget = { 15 | bubble: Bubble, 16 | page: Page, 17 | command: BubbleInspectorCommand | null, 18 | commandTargetFilm: Film | null, 19 | } 20 | 21 | export const bubbleInspectorTarget: Writable = writable(null); 22 | export const bubbleSplitCursor: Writable = writable(null); 23 | export const bubbleInspectorRebuildToken: Writable = writable(0); 24 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/fontStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, type Writable } from "svelte/store"; 2 | 3 | export const chosenFont: Writable<{ fontFamily: string, fontWeight: string } | null> = writable(null); 4 | export const fontChooserOpen = writable(false); 5 | 6 | export type SearchOptions = { filterString: string, mincho: boolean, gothic: boolean, normal: boolean, bold: boolean } 7 | -------------------------------------------------------------------------------- /src/bookeditor/bubbleinspector/shapeStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, type Writable } from "svelte/store"; 2 | 3 | export const shapeChooserOpen: Writable = writable(false); 4 | export const chosenShape: Writable = writable('soft'); 5 | 6 | -------------------------------------------------------------------------------- /src/bookeditor/effectchooser/EffectChooser.svelte: -------------------------------------------------------------------------------- 1 | 20 | 21 |
22 | 23 |
24 |
25 | {#each effects as { name, label, hint }} 26 | 33 | {/each} 34 |
35 |
36 |
37 |
38 | 39 | -------------------------------------------------------------------------------- /src/bookeditor/effectchooser/effectChooserStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | 3 | export type EffectChoiceNotifier = (tag: string | null) => void; 4 | 5 | export const effectChoiceNotifier: Writable = writable(null); 6 | -------------------------------------------------------------------------------- /src/bookeditor/frameinspector/frameInspectorStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | import type { FrameElement } from "../../lib/layeredCanvas/dataModels/frameTree"; 3 | import type { Film } from "../../lib/layeredCanvas/dataModels/film"; 4 | import type { Page } from '../../lib/book/book'; 5 | 6 | type FrameInspectorCommand = "generate" | "scribble" | "punch" | "outpainting"; 7 | 8 | export type FrameInspectorPosition = { 9 | center: {x: number, y: number}, 10 | height: number, 11 | offset: number, 12 | } 13 | 14 | export type FrameInspectorTarget = { 15 | frame: FrameElement, 16 | page: Page, 17 | command: FrameInspectorCommand | null, 18 | commandTargetFilm: Film | null, 19 | } 20 | 21 | export const frameInspectorTarget: Writable = writable(null); 22 | export const frameInspectorRebuildToken: Writable = writable(0); 23 | -------------------------------------------------------------------------------- /src/bookeditor/pageinspector/pageInspectorStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | import type { Page } from '../../lib/book/book'; 3 | 4 | export const pageInspectorTarget: Writable = writable(null); 5 | -------------------------------------------------------------------------------- /src/bookeditor/templateChooserStore.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncStore } from "../utils/asyncStore"; 2 | 3 | export const triggerTemplateChoice = createAsyncStore(); 4 | -------------------------------------------------------------------------------- /src/box.css: -------------------------------------------------------------------------------- 1 | .hbox { 2 | display: flex; 3 | flex-direction: row; 4 | align-items: center; 5 | justify-content: center; 6 | } 7 | .hbox.left {justify-content: flex-start;} 8 | .hbox.right {justify-content: flex-end;} 9 | .hbox.center {justify-content: center;} 10 | .hbox.space-around {justify-content: space-around;} 11 | .hbox.top {align-items: start;} 12 | .hbox.bottom {align-items: end;} 13 | .hbox.vcenter { align-items: center; } 14 | .hbox.gap {gap: 12px;} 15 | .hbox.stretch-child {align-items: stretch;} 16 | .hbox .expand {align-self: stretch;} 17 | .hbox .grow {flex-grow: 1;} 18 | 19 | .vbox { 20 | display: flex; 21 | flex-direction: column; 22 | align-items: center; 23 | } 24 | .vbox.top {justify-content: flex-start;} 25 | .vbox.bottom {justify-content: flex-end;} 26 | .vbox.center {justify-content: center;} 27 | .vbox.left {align-items: start;} 28 | .vbox.right {align-items: end;} 29 | .vbox.hcenter { align-items: center; } 30 | .vbox.gap {gap: 12px;} 31 | .vbox.stretch-child {align-items: stretch;} 32 | .vbox.space-around {justify-content: space-around;} 33 | .vbox .expand {align-self: stretch;} 34 | .vbox .grow {flex-grow: 1;} -------------------------------------------------------------------------------- /src/bubbleBucket/BubbleBucketItem.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 |
29 | 30 |
31 | 32 | 52 | -------------------------------------------------------------------------------- /src/bubbleBucket/bubbleBucketStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, type Writable } from "svelte/store"; 2 | import type { Page } from "../lib/book/book"; 3 | 4 | export const bubbleBucketPage: Writable = writable(null); 5 | export const bubbleBucketDirty = writable(false); 6 | -------------------------------------------------------------------------------- /src/controlpanel/controlPanelStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const controlPanelOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/customTypes.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'css-font-parser'; 2 | -------------------------------------------------------------------------------- /src/downloader/downloaderStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const downloaderOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/filemanager/FileManager.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 | {#await fileSystemPromise} 15 |
loading...
16 | {:then fileSystem} 17 | 18 | {/await} 19 | -------------------------------------------------------------------------------- /src/filemanager/FileManagerFolderTail.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 | 45 | -------------------------------------------------------------------------------- /src/filemanager/FileManagerInsertZone.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 | 31 |
39 |
43 |
44 |
45 | 46 | 47 | 83 | 84 | -------------------------------------------------------------------------------- /src/filemanager/currentFile.ts: -------------------------------------------------------------------------------- 1 | // 現在のファイルIDをSessionStorageに記録する関数 2 | import type { NodeId } from '../lib/filesystem/fileSystem'; 3 | 4 | export type CurrentFileInfo = { 5 | id: NodeId; 6 | fileSystem: 'cloud' | 'local'; 7 | } 8 | 9 | export async function recordCurrentFileInfo(info: CurrentFileInfo): Promise { 10 | sessionStorage.setItem('currentFileId', JSON.stringify(info)); 11 | } 12 | 13 | // SessionStorageから現在のファイルIDを取得する関数 14 | export async function fetchCurrentFileInfo(): Promise { 15 | const info = sessionStorage.getItem('currentFileId'); 16 | if (!info) { return null; } 17 | 18 | try { 19 | const parsed = JSON.parse(info); 20 | return parsed; 21 | } 22 | catch { 23 | // 互換性 24 | return {id: info as NodeId, fileSystem: 'local'}; 25 | } 26 | } 27 | 28 | export async function clearCurrentFileInfo(): Promise { 29 | sessionStorage.removeItem('currentFileId'); 30 | } 31 | -------------------------------------------------------------------------------- /src/filemanager/developmentFileSystem.ts: -------------------------------------------------------------------------------- 1 | import { type FileSystem, makeFolders } from '../lib/filesystem/fileSystem'; 2 | import { MockFileSystem } from '../lib/filesystem/mockFileSystem'; 3 | import { specialFolders } from './specialFolders'; 4 | 5 | export async function buildFileSystem(): Promise { 6 | const fs = new MockFileSystem(); 7 | 8 | await makeFolders(fs, specialFolders); 9 | 10 | return fs; 11 | } 12 | -------------------------------------------------------------------------------- /src/filemanager/productionFileSystem.ts: -------------------------------------------------------------------------------- 1 | import { type FileSystem, makeFolders } from '../lib/filesystem/fileSystem'; 2 | import { IndexedDBFileSystem } from '../lib/filesystem/indexeddbFileSystem'; 3 | import { specialFolders } from './specialFolders'; 4 | 5 | export async function buildFileSystem(): Promise { 6 | const fs = new IndexedDBFileSystem(); 7 | await fs.open(); 8 | 9 | await makeFolders(fs, specialFolders); 10 | 11 | return fs; 12 | } 13 | -------------------------------------------------------------------------------- /src/filemanager/shareFileSystem.ts: -------------------------------------------------------------------------------- 1 | import { FirebaseFileSystem } from '../lib/filesystem/firebaseFileSystem'; 2 | import { makeFolders } from '../lib/filesystem/fileSystem'; 3 | 4 | export async function buildShareFileSystem(referenceUserId: string | null): Promise { 5 | const fs = new FirebaseFileSystem(); 6 | await fs.openShared(referenceUserId); 7 | 8 | const specialFolders = ['画像']; 9 | await makeFolders(fs, specialFolders); 10 | 11 | return fs; 12 | } 13 | 14 | export async function buildCloudFileSystem(): Promise { 15 | const fs = new FirebaseFileSystem(); 16 | await fs.openCloud(); 17 | 18 | // garbageCollectionがデスクトップ前提になっているので 19 | const specialFolders = ['デスクトップ', 'キャビネット', 'ごみ箱', 'テンプレート', '画像', 'プリファレンス', '素材']; 20 | await makeFolders(fs, specialFolders); 21 | 22 | return fs; 23 | } 24 | -------------------------------------------------------------------------------- /src/filemanager/specialFolders.ts: -------------------------------------------------------------------------------- 1 | export const specialFolders = ["デスクトップ", "キャビネット", "ごみ箱", "テンプレート", "画像", "動画", "プリファレンス", "素材", "AI"]; 2 | -------------------------------------------------------------------------------- /src/generator/FluxModes.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | 27 | 28 |
29 | Schnell 30 | 31 |
32 |
33 | 34 |
35 | Pro 36 | 37 |
38 |
39 | 40 |
41 | ちび 42 | 43 |
44 |
45 | 46 |
47 | まんが 48 | 49 |
50 |
51 |
52 | {#if comment} 53 |
{comment}
54 | {/if} 55 |
56 | 57 | 70 | 71 | -------------------------------------------------------------------------------- /src/generator/Gallery.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 | 38 | 39 | -------------------------------------------------------------------------------- /src/generator/ImageGeneratorPlain.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 | 32 |
33 |
34 | 35 | 53 | -------------------------------------------------------------------------------- /src/generator/ImageProvider.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
18 | 19 |
20 | 21 | -------------------------------------------------------------------------------- /src/generator/ImagingProgressBar.svelte: -------------------------------------------------------------------------------- 1 | 8 | 9 |
10 |

画像生成中

11 | 12 |
13 | 14 |
15 | 16 | {#if imageProgress !== null} 17 |
18 | 19 |
20 | {/if} 21 |
22 | 23 | -------------------------------------------------------------------------------- /src/generator/batchImagingStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable, get } from "svelte/store"; 2 | import type { Page } from "../lib/book/book"; 3 | 4 | export const batchImagingPage: Writable = writable(null); 5 | export const busy: Writable = writable(false); 6 | 7 | export async function execute(child: any) { 8 | console.log('execute'); 9 | busy.set(true); 10 | await child.excecute(get(batchImagingPage)); 11 | busy.set(false); 12 | console.log('execute done'); 13 | } 14 | -------------------------------------------------------------------------------- /src/generator/imageGeneratorStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | import type { FilmStack } from "../lib/layeredCanvas/dataModels/film"; 3 | 4 | export type ImageGeneratorTarget = { 5 | filmStack: FilmStack; 6 | initialPrompt: string | null; 7 | gallery: HTMLCanvasElement[]; 8 | onDone: (r: {canvas: HTMLCanvasElement, prompt: string} | null) => void, 9 | } 10 | 11 | export const imageGeneratorTarget: Writable = writable(null); 12 | -------------------------------------------------------------------------------- /src/lib/book/layout.ts: -------------------------------------------------------------------------------- 1 | import * as t from "io-ts"; 2 | import {annotate} from "typai"; 3 | 4 | export const LayoutColumn = annotate( 5 | t.type({ 6 | id: annotate(t.string, {description: "対応する入力要素のid"}), 7 | ratio: annotate(t.number, {description: "兄弟間でのratio(weightに比例する)"}), 8 | }), 9 | {description: "横方向要素、1~2要素 すべてのコマの重要度が低い場合は3要素も許される"} 10 | ); 11 | export type LayoutColumn = t.TypeOf; 12 | 13 | export const LayoutRow = annotate( 14 | t.type({ 15 | columns: t.array(LayoutColumn), 16 | ratio: annotate(t.number, {description: "兄弟間でのratio(weightに比例する)"}), 17 | }), 18 | {description: "縦方向要素(段)、1~3要素"} 19 | ); 20 | export type LayoutRow = t.TypeOf; 21 | 22 | export const LayoutPage = annotate( 23 | t.type({ 24 | rows: t.array(LayoutRow), 25 | }), 26 | {description: "ページ"} 27 | ); 28 | export type LayoutPage = t.TypeOf; 29 | 30 | -------------------------------------------------------------------------------- /src/lib/book/notebook.ts: -------------------------------------------------------------------------------- 1 | import * as t from "io-ts"; 2 | import { ignore } from "typai"; 3 | import { Storyboard } from "./storyboard"; 4 | 5 | export const Character = t.type({ 6 | ulid: ignore(t.string), 7 | name: t.string, 8 | personality: t.string, 9 | appearance: t.string, 10 | themeColor: t.string, 11 | portrait: ignore(t.any), // 'loading' | HTMLImageElement 12 | }); 13 | 14 | export const Notebook = t.type({ 15 | theme: t.string, 16 | characters: t.array(Character), 17 | plot: t.string, 18 | scenario: t.string, 19 | storyboard: t.union([Storyboard, t.null]), 20 | critique: t.string, 21 | }); 22 | 23 | export type Character = t.TypeOf; 24 | export type Notebook = t.TypeOf; 25 | 26 | export function emptyNotebook(): Notebook { 27 | return { 28 | theme: "", 29 | characters: [], 30 | plot: "", 31 | scenario: "", 32 | storyboard: null, 33 | critique: "", 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /src/lib/filesystem/contentStorage/contentStorage.ts: -------------------------------------------------------------------------------- 1 | export type ContentId = string & {_ImageId: never}; // SHA1 2 | 3 | export interface ContentStorage { 4 | readBlob(id: ContentId): Promise; 5 | writeBlob(blob: Blob): Promise; 6 | readCanvas(id: ContentId): Promise; 7 | writeCanvas(canvas: HTMLCanvasElement): Promise; 8 | erase(id: ContentId): Promise; 9 | }; 10 | 11 | export abstract class ContentStorageBase implements ContentStorage { 12 | abstract readBlob(id: ContentId): Promise; 13 | abstract writeBlob(blob: Blob): Promise; 14 | abstract readCanvas(id: ContentId): Promise; 15 | abstract writeCanvas(canvas: HTMLCanvasElement): Promise; 16 | abstract erase(id: ContentId): Promise; 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/layers/SampleLayer.ts: -------------------------------------------------------------------------------- 1 | import { LayerBase } from "../system/layeredCanvas"; 2 | 3 | // 動作確認用 4 | 5 | export class SampleLayer extends LayerBase { 6 | constructor() { 7 | super(); 8 | } 9 | 10 | render(ctx: CanvasRenderingContext2D, depth: number): void { 11 | if (depth !== 0) { return; } 12 | 13 | // 中央に三角形 14 | ctx.beginPath(); 15 | ctx.moveTo(0, 0); 16 | ctx.lineTo(100, 0); 17 | ctx.lineTo(0, 100); 18 | ctx.closePath(); 19 | ctx.fillStyle = "red"; 20 | ctx.fill(); 21 | 22 | } 23 | 24 | renderDepths(): number[] { return [0]; } 25 | } -------------------------------------------------------------------------------- /src/lib/layeredCanvas/layers/undoLayer.ts: -------------------------------------------------------------------------------- 1 | import { LayerBase } from "../system/layeredCanvas"; 2 | import type { Vector } from "../tools/geometry/geometry"; 3 | 4 | export class UndoLayer extends LayerBase { 5 | onUndo: () => void; 6 | onRedo: () => void; 7 | 8 | constructor(onUndo: ()=>void, onRedo: () => void) { 9 | super(); 10 | this.onUndo = onUndo; 11 | this.onRedo = onRedo; 12 | } 13 | 14 | async keyDown(position_: Vector, event: KeyboardEvent): Promise { 15 | if (event.code === "KeyZ") { 16 | if (event.ctrlKey && event.shiftKey) { 17 | this.onRedo(); 18 | return true; 19 | } else if (event.ctrlKey) { 20 | this.onUndo(); 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/system/keyCache.ts: -------------------------------------------------------------------------------- 1 | export const keyDownFlags: { [key: string]: boolean } = {}; 2 | 3 | export function initializeKeyCache(canvas: HTMLCanvasElement, consume: (code: string) => boolean) { 4 | if ((canvas as any)["keyCacheInitialized"]) { return; } 5 | (canvas as any)["keyCacheInitialized"] = true; 6 | 7 | function getCanvasPosition(event: MouseEvent) { 8 | const rect = canvas.getBoundingClientRect(); 9 | const x = event.clientX - rect.left; 10 | const y = event.clientY - rect.top; 11 | return [x, y]; 12 | } 13 | 14 | let mouseCursor = [-1, -1]; 15 | function isMouseOnCanvas() { 16 | var rect = canvas.getBoundingClientRect(); 17 | 18 | // カーソルの座標がキャンバスの範囲内にあるかをチェック 19 | var isInCanvas = 20 | 0 <= mouseCursor[0] - rect.left && 21 | mouseCursor[0] - rect.left <= rect.width && 22 | 0 <= mouseCursor[1] - rect.top && 23 | mouseCursor[1] - rect.top <= rect.height; 24 | 25 | // カーソルの座標に最前面の要素がキャンバスかどうかをチェック 26 | if (isInCanvas) { 27 | var elementAtCursor = document.elementFromPoint( 28 | mouseCursor[0], 29 | mouseCursor[1] 30 | ); 31 | return elementAtCursor === canvas; 32 | } 33 | 34 | return false; 35 | } 36 | 37 | canvas.addEventListener("mousemove", (event) => { 38 | mouseCursor = getCanvasPosition(event); 39 | }); 40 | canvas.addEventListener("mouseleave", (event) => { 41 | mouseCursor = [-1, -1]; 42 | }); 43 | document.addEventListener("keydown", (event) => { 44 | if (!isMouseOnCanvas()) { 45 | return; 46 | } 47 | let code = event.code; 48 | if (code == "MetaLeft") { 49 | code = "ControlLeft"; 50 | } 51 | if (code == "MetaRight") { 52 | code = "ControlRight"; 53 | } 54 | if (!consume(code)) { 55 | return; 56 | } 57 | keyDownFlags[code] = true; 58 | event.preventDefault(); 59 | }); 60 | document.addEventListener("keyup", (event) => { 61 | keyDownFlags[event.code] = false; 62 | event.preventDefault(); 63 | }); 64 | canvas.addEventListener("mouseleave", (event) => { 65 | for (let key in keyDownFlags) { 66 | delete keyDownFlags[key]; 67 | } 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/draw/drawFilmStack.ts: -------------------------------------------------------------------------------- 1 | import type { FilmStack } from '../../dataModels/film'; 2 | import type { Vector } from '../geometry/geometry'; 3 | 4 | export function drawFilmStack(ctx: CanvasRenderingContext2D, filmStack: FilmStack, paperSize: Vector) { 5 | const films = filmStack.films; 6 | 7 | for (let film of films) { 8 | if (!film.visible) { continue; } 9 | 10 | const scale = film.getShiftedScale(paperSize); 11 | const translation = film.getShiftedTranslation(paperSize); 12 | 13 | ctx.save(); 14 | ctx.translate(translation[0], translation[1]); 15 | ctx.rotate(-film.rotation * Math.PI / 180); 16 | ctx.scale(scale * film.reverse[0], scale * film.reverse[1]); 17 | 18 | let media = film.media; 19 | for (let i = film.effects.length - 1; 0 <= i; i--) { 20 | if (film.effects[i].outputMedia) { 21 | media = film.effects[i].outputMedia!; 22 | break; 23 | } 24 | } 25 | 26 | ctx.save(); 27 | ctx.translate(-media.naturalWidth * 0.5, -media.naturalHeight * 0.5); 28 | ctx.drawImage(media.drawSource, 0, 0, media.naturalWidth, media.naturalHeight); 29 | ctx.restore(); 30 | 31 | ctx.restore(); 32 | } 33 | } 34 | 35 | export function drawFilmStackBorders(ctx: CanvasRenderingContext2D, filmStack: FilmStack, paperSize: Vector) { 36 | const films = filmStack.films; 37 | 38 | for (let film of films) { 39 | if (!film.visible) { continue; } 40 | 41 | const scale = film.getShiftedScale(paperSize); 42 | const translation = film.getShiftedTranslation(paperSize); 43 | 44 | ctx.save(); 45 | ctx.translate(translation[0], translation[1]); 46 | ctx.rotate(-film.rotation * Math.PI / 180); 47 | 48 | if (film.visible) { 49 | const sx = scale * film.reverse[0]; 50 | const sy = scale * film.reverse[1]; 51 | const iw = sx * film.media.naturalWidth; 52 | const ih = sy * film.media.naturalHeight; 53 | 54 | ctx.save(); 55 | ctx.translate(-iw * 0.5, -ih * 0.5); 56 | ctx.strokeStyle = '#00000080'; 57 | ctx.lineWidth = 1; 58 | ctx.strokeRect(0, 0, iw, ih); 59 | ctx.restore(); 60 | } 61 | ctx.restore(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/draw/selectionFrame.ts: -------------------------------------------------------------------------------- 1 | import { type Trapezoid, trapezoidPath, trapezoidBoundingRect } from "../geometry/trapezoid"; 2 | import { type Vector, type Rect, extendRect, ensureMinRectSize, scale2D } from '../geometry/geometry'; 3 | import paper from 'paper'; 4 | 5 | const SHEET_MARGIN = 16; 6 | 7 | export function drawSelectionFrame(ctx: CanvasRenderingContext2D, color: string, trapezoid: Trapezoid, nearLineWidth: number = 7, farLineWidth = 10, drawsCircles = true) { 8 | ctx.save(); 9 | 10 | // まず白で枠を描く 11 | ctx.strokeStyle = "rgba(255, 255, 255, 0.8)"; 12 | ctx.setLineDash([]); 13 | ctx.lineWidth = farLineWidth; 14 | ctx.beginPath(); 15 | trapezoidPath(ctx, trapezoid); 16 | ctx.stroke(); 17 | 18 | // 指定された色で点線を描く 19 | ctx.strokeStyle = color; 20 | ctx.lineWidth = nearLineWidth; 21 | ctx.setLineDash([20, 20]); 22 | ctx.beginPath(); 23 | trapezoidPath(ctx, trapezoid); 24 | ctx.stroke(); 25 | ctx.setLineDash([]); 26 | 27 | const drawCircle = (p: Vector) => { 28 | ctx.beginPath(); 29 | ctx.arc(p[0], p[1], farLineWidth, 0, Math.PI * 2); 30 | ctx.fill(); 31 | ctx.stroke(); 32 | } 33 | 34 | // 四隅に円を書く 35 | if (drawsCircles) { 36 | ctx.fillStyle = "rgba(255, 255, 255, 1)"; 37 | drawCircle(trapezoid.topLeft); 38 | drawCircle(trapezoid.topRight); 39 | drawCircle(trapezoid.bottomLeft); 40 | drawCircle(trapezoid.bottomRight); 41 | } 42 | 43 | ctx.restore(); 44 | } 45 | 46 | export function calculateSheetRect(rect: Rect, minSize: Vector, ymargin: number, rscale: number): Rect { 47 | const r = extendRect(rect, SHEET_MARGIN * rscale); 48 | r[1] -= ymargin * rscale; 49 | r[3] += ymargin * rscale * 2; 50 | return ensureMinRectSize(scale2D(minSize, rscale), r); 51 | } 52 | 53 | export function drawSheet(ctx: CanvasRenderingContext2D, corners: Trapezoid, r: Rect, fillStyle: string) { 54 | const paperr = new paper.Rectangle(...r); 55 | const path1 = new paper.Path.Rectangle(paperr, [8, 8]); 56 | 57 | const path2 = new paper.Path(); 58 | const points = [corners.topLeft, corners.topRight, corners.bottomRight, corners.bottomLeft]; 59 | for (let i = 0; i < points.length; i++) { 60 | const p = points[i]; 61 | if (i === 0) { 62 | path2.moveTo(p as Vector); 63 | } else { 64 | path2.lineTo(p as Vector); 65 | } 66 | } 67 | path2.closed = true; 68 | 69 | const path3 = path1.subtract(path2); 70 | 71 | ctx.fillStyle = fillStyle; 72 | ctx.fill(new Path2D(path3.pathData)); 73 | } 74 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/draw/typeSetting.ts: -------------------------------------------------------------------------------- 1 | import { type RichFragment } from "./richText"; 2 | 3 | export interface Rectangle { 4 | x: number; 5 | y: number; 6 | width: number; 7 | height: number; 8 | } 9 | 10 | export interface RenderingText { 11 | height: number; 12 | width: number; 13 | verticalLines?: RichFragment[][]; 14 | horizontalLines?: { text: string }[]; 15 | } 16 | 17 | export type DrawMethod = "fill" | "stroke"; 18 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/focusKeeper.ts: -------------------------------------------------------------------------------- 1 | import type { Layer } from "../system/layeredCanvas"; 2 | 3 | export class FocusKeeper { 4 | subscribers: ((layer: Layer | null) => void)[] = []; 5 | 6 | constructor() { 7 | 8 | } 9 | 10 | subscribe(f: (layer: Layer | null) => void) { 11 | this.subscribers.push(f); 12 | } 13 | 14 | unsubscribe(f: (layer: Layer) => void) { 15 | this.subscribers = this.subscribers.filter((s) => s !== f); 16 | } 17 | 18 | setFocus(layer: Layer | null) { 19 | this.subscribers.forEach((s) => s(layer)); 20 | } 21 | } -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/geometry/convertPoint.ts: -------------------------------------------------------------------------------- 1 | function getTransformationMatrix(element: HTMLElement) { 2 | let transformationMatrix = new DOMMatrix(); 3 | let x = element; 4 | 5 | while (x && x !== document.documentElement) { 6 | const transform = window.getComputedStyle(x).transform; 7 | transformationMatrix = new DOMMatrix(transform).multiply(transformationMatrix); 8 | x = x.parentElement!; 9 | } 10 | 11 | const rect = element.getBoundingClientRect(); 12 | transformationMatrix = new DOMMatrix() 13 | .translate(rect.left + window.scrollX, rect.top + window.scrollY) 14 | .multiply(transformationMatrix); 15 | 16 | return transformationMatrix; 17 | } 18 | 19 | export function convertPointFromPageToNode(element: HTMLElement, pageX: number, pageY: number) { 20 | const point = new DOMPoint(pageX, pageY); 21 | return point.matrixTransform(getTransformationMatrix(element).inverse()); 22 | }; 23 | 24 | export function convertPointFromNodeToPage(element: HTMLElement, offsetX: number, offsetY: number) { 25 | const point = new DOMPoint(offsetX, offsetY); 26 | return point.matrixTransform(getTransformationMatrix(element)); 27 | }; 28 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/geometry/geometry.vitest.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { testSegmentIntersection, type Vector } from './geometry'; 3 | 4 | describe('segmentIntersection', () => { 5 | it('should return null for parallel lines', () => { 6 | const s0: [Vector, Vector] = [[0, 0], [1, 1]]; 7 | const s1: [Vector, Vector] = [[0, 1], [1, 2]]; 8 | expect(testSegmentIntersection(s0, s1)).toBeNull(); 9 | }); 10 | 11 | it('should return null for non-intersecting lines', () => { 12 | const s0: [Vector, Vector] = [[0, 0], [1, 0]]; 13 | const s1: [Vector, Vector] = [[0, 1], [1, 1]]; 14 | expect(testSegmentIntersection(s0, s1)).toBeNull(); 15 | }); 16 | 17 | it('should return the correct intersection point for intersecting lines', () => { 18 | const s0: [Vector, Vector] = [[0, 0], [2, 2]]; 19 | const s1: [Vector, Vector] = [[0, 2], [2, 0]]; 20 | const result = testSegmentIntersection(s0, s1); 21 | expect(result).not.toBeNull(); 22 | if (result) { 23 | const [t, p] = result; 24 | expect(t).toBeCloseTo(0.5); 25 | expect(p).toEqual([1, 1]); 26 | } 27 | }); 28 | 29 | it('should return null when the intersection point is outside the segments', () => { 30 | const s0: [Vector, Vector] = [[0, 0], [1, 1]]; 31 | const s1: [Vector, Vector] = [[2, 2], [3, 3]]; 32 | expect(testSegmentIntersection(s0, s1)).toBeNull(); 33 | }); 34 | 35 | it('should handle vertical and horizontal lines correctly', () => { 36 | const s0: [Vector, Vector] = [[1, 0], [1, 2]]; 37 | const s1: [Vector, Vector] = [[0, 1], [2, 1]]; 38 | const result = testSegmentIntersection(s0, s1); 39 | expect(result).not.toBeNull(); 40 | if (result) { 41 | const [t, p] = result; 42 | expect(t).toBeCloseTo(0.5); 43 | expect(p).toEqual([1, 1]); 44 | } 45 | }); 46 | 47 | it('should handle overlapping lines by returning null', () => { 48 | const s0: [Vector, Vector] = [[0, 0], [2, 2]]; 49 | const s1: [Vector, Vector] = [[1, 1], [3, 3]]; 50 | expect(testSegmentIntersection(s0, s1)).toBeNull(); 51 | }); 52 | 53 | it('should handle endpoints touching as intersecting', () => { 54 | const s0: [Vector, Vector] = [[0, 0], [1, 1]]; 55 | const s1: [Vector, Vector] = [[1, 1], [2, 0]]; 56 | const result = testSegmentIntersection(s0, s1); 57 | expect(result).not.toBeNull(); 58 | if (result) { 59 | const [t, p] = result; 60 | expect(t).toBeCloseTo(1); 61 | expect(p).toEqual([1, 1]); 62 | } 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/grid.ts: -------------------------------------------------------------------------------- 1 | import { type Vector, type Rect, extendRect } from './geometry/geometry'; 2 | 3 | export class Grid { 4 | rect: Rect; 5 | 6 | constructor(rect: Rect, margin: number, private cellUnit: Vector) { 7 | this.rect = extendRect(rect, margin); 8 | } 9 | 10 | calcPosition(regularizedOrigin: Vector, offsetUnit: Vector): Vector { 11 | const unit = this.cellUnit; 12 | const [x, y, w, h] = this.rect; 13 | const origin = [x + w * regularizedOrigin[0], y + h * regularizedOrigin[1]]; 14 | return [origin[0] + unit[0] * offsetUnit[0], origin[1] + unit[1] * offsetUnit[1]]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/haiku.ts: -------------------------------------------------------------------------------- 1 | const haiku = [ 2 | "古池や\n蛙飛び込む\n水の音", 3 | "夏草や\n兵どもが\n夢の跡", 4 | "柿食えば\n鐘が鳴るなり\n法隆寺", 5 | "秋深き\n隣は何を\nする人ぞ", 6 | "朝顔に\nつるべとられて\nもらい水", 7 | "五月雨を\n集めてはやし\n最上川", 8 | "すずめの子\nそこのけそこのけ\nお馬が通る", 9 | "菜の花や\n月は東に\n日は西に", 10 | "目には青葉\nやまほととぎす\n初がつお", 11 | "やせ蛙\n負けるな一茶\nこれにあり", 12 | "閑さや\n岩にしみ入る\n蝉の声", 13 | ]; 14 | 15 | export function getHaiku(): string { 16 | return haiku[Math.floor(Math.random() * haiku.length)]; 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/misc.ts: -------------------------------------------------------------------------------- 1 | export function arrayVectorToObjectVector(v: [number, number]) { 2 | return {x:v[0], y:v[1]}; 3 | } 4 | 5 | export function objectVectorToArrayVector(v: {x: number, y: number}) { 6 | return [v.x, v.y]; 7 | } 8 | 9 | export function documentCoordToElementCoord(e: HTMLElement, p: {x: number, y: number}) { 10 | let rect = e.getBoundingClientRect(); 11 | return {x: p.x - rect.left, y:p.y - rect.top}; 12 | } 13 | 14 | export function elementCoordToDocumentCoord(e: HTMLElement, p: {x: number, y: number}) { 15 | let rect = e.getBoundingClientRect(); 16 | return {x: p.x + rect.left, y:p.y + rect.top}; 17 | } 18 | 19 | function isObject(item: any) { 20 | return (item && typeof item === 'object' && !Array.isArray(item)); 21 | } 22 | 23 | export function deepCopyProperties(target: any, source: any) { 24 | Object.keys(source).forEach(key => { 25 | if (isObject(source[key])) { 26 | if (!target[key]) target[key] = {}; 27 | deepCopyProperties(target[key], source[key]); 28 | } else { 29 | target[key] = source[key]; 30 | } 31 | }); 32 | return target; 33 | } 34 | 35 | export async function sha1(message: string) { 36 | const encoder = new TextEncoder(); 37 | const data = encoder.encode(message); 38 | const hashBuffer = await crypto.subtle.digest('SHA-1', data); 39 | const hashArray = Array.from(new Uint8Array(hashBuffer)); 40 | const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); 41 | return hashHex; 42 | } 43 | 44 | export async function blobToSha1(blob: Blob) { 45 | const buffer = await blob.arrayBuffer(); 46 | const hashBuffer = await crypto.subtle.digest('SHA-1', buffer); 47 | const hashArray = Array.from(new Uint8Array(hashBuffer)); 48 | const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join(''); 49 | return hashHex; 50 | } 51 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/paper.d.ts: -------------------------------------------------------------------------------- 1 | declare module paper { 2 | export class Path extends paper.PathItem { 3 | closed: boolean; 4 | readonly pathData: string; 5 | addSegments(segments: paper.SegmentLike[] | paper.PointLike[]): void; 6 | moveTo(point: paper.PointLike): void; 7 | lineTo(point: paper.PointLike): void; 8 | rotate(angle: number, center: paper.PointLike): void; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/perfectFreehandUtil.ts: -------------------------------------------------------------------------------- 1 | import { type Vector } from './geometry/geometry' 2 | 3 | const average = (a: number, b: number) => (a + b) / 2 4 | 5 | export function getSvgPathFromStroke(points: Vector[], closed = true) { 6 | const len = points.length 7 | 8 | if (len < 4) { 9 | return `` 10 | } 11 | 12 | let a = points[0] 13 | let b = points[1] 14 | const c = points[2] 15 | 16 | let result = `M${a[0].toFixed(2)},${a[1].toFixed(2)} Q${b[0].toFixed( 17 | 2 18 | )},${b[1].toFixed(2)} ${average(b[0], c[0]).toFixed(2)},${average( 19 | b[1], 20 | c[1] 21 | ).toFixed(2)} T` 22 | 23 | for (let i = 2, max = len - 1; i < max; i++) { 24 | a = points[i] 25 | b = points[i + 1] 26 | result += `${average(a[0], b[0]).toFixed(2)},${average(a[1], b[1]).toFixed( 27 | 2 28 | )} ` 29 | } 30 | 31 | if (closed) { 32 | result += 'Z' 33 | } 34 | 35 | return result 36 | } 37 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/pictureControl.ts: -------------------------------------------------------------------------------- 1 | import type { Vector } from './geometry/geometry'; 2 | 3 | export function *translate(p: Vector, f: (t: Vector) => void) { 4 | let dragStart = p; 5 | 6 | while (p = yield) { 7 | const dragOffset: Vector = [p[0] - dragStart[0], p[1] - dragStart[1]]; 8 | f(dragOffset); 9 | } 10 | } 11 | 12 | export function *scale([w, h]: Vector, p: Vector, f: (s: Vector) => void) { 13 | let dragStart = p; 14 | 15 | while (p = yield) { 16 | const dragOffset = [p[0] - dragStart[0], p[1] - dragStart[1]]; 17 | let xScale = 1 + dragOffset[0] / w; 18 | let yScale = 1 + dragOffset[0] / h; 19 | f([xScale, yScale]); 20 | } 21 | } 22 | 23 | export function *rotate(p: Vector, f: (r: number) => void) { 24 | let dragStart = p; 25 | 26 | while (p = yield) { 27 | const dragOffset = p[0] - dragStart[0]; 28 | f(dragOffset); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/lib/layeredCanvas/tools/rectHandle.ts: -------------------------------------------------------------------------------- 1 | export type RectCornerHandle = 2 | "topLeft"| 3 | "topRight"| 4 | "bottomLeft"| 5 | "bottomRight"; 6 | 7 | export type RectSideHandle = 8 | "top"| 9 | "bottom"| 10 | "left"| 11 | "right"; 12 | 13 | export type RectHandle = RectCornerHandle | RectSideHandle; 14 | 15 | export const rectCornerHandles: RectCornerHandle[] = [ 16 | "topLeft", 17 | "topRight", 18 | "bottomLeft", 19 | "bottomRight" 20 | ]; 21 | 22 | export const rectSideHandles: RectSideHandle[] = [ 23 | "top", 24 | "bottom", 25 | "left", 26 | "right" 27 | ]; 28 | 29 | export const rectHandles: RectHandle[] = [ 30 | ...rectCornerHandles, 31 | ...rectSideHandles 32 | ]; 33 | -------------------------------------------------------------------------------- /src/lib/sample.test.ts: -------------------------------------------------------------------------------- 1 | import 'fake-indexeddb/auto'; 2 | import { describe, it, expect } from 'vitest'; 3 | 4 | describe('Sample Test', () => { 5 | it('should display Node.js version', () => { 6 | console.log('window:', typeof window !== 'undefined'); 7 | console.log('indexedDB:', typeof indexedDB !== 'undefined'); 8 | console.log('window.indexedDB:', window.indexedDB); 9 | expect(indexedDB).toBeDefined(); 10 | }); 11 | }); -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import "./app.postcss"; 2 | import App from "./App.svelte"; 3 | import { initializeApp } from "./firebase"; 4 | import { initPaperJs } from "./lib/layeredCanvas/tools/draw/bubbleGraphic" 5 | 6 | window.name = "frameplanner"; 7 | 8 | initPaperJs(); 9 | 10 | function getDomainFromCurrentUrl(): string { 11 | const currentUrl = window.location.href; 12 | const urlObj = new URL(currentUrl); 13 | return urlObj.host; 14 | } 15 | initializeApp(getDomainFromCurrentUrl()) 16 | 17 | const app = new App({ 18 | target: document.getElementById("app")!, 19 | }); 20 | 21 | export default app; 22 | 23 | // console.tagという関数を定義 24 | // console.tag("commit", page.revision, [...page.history], page.historyIndex) とすると 25 | // console.log("%ccommit", "color:white; background-color:cyan; padding:2px 4px; border-radius:4px;", page.revision, [...page.history], page.historyIndex) 26 | // のように展開される 27 | 28 | declare global { 29 | export interface Console { 30 | tag(tag: string, ...args: any[]): void; 31 | snapshot(obj: any): void; 32 | } 33 | } 34 | 35 | console.tag = function(tag, color, ...args) { 36 | console.log(`%c${tag}`, `color:white; background-color:${color}; padding:2px 4px; border-radius:4px;`, ...args); 37 | // console.trace(); 38 | } 39 | 40 | console.snapshot = function(obj) { 41 | // chromeのデバッガではその後に値を変更されてもコンソール出力に反映されてしまうので、 42 | // JSON.parse(JSON.stringify(obj)) でコピーを作成している 43 | const s = JSON.parse(JSON.stringify(obj, null, 2)); 44 | console.tag("snapshot", "#778899", s); 45 | } 46 | 47 | function loadFont(family: string, filename: string, weight: string) { 48 | const url = `/fonts/${filename}.woff2`; 49 | console.log(`loading font: ${family} ${weight} ${url}`); 50 | const font = new FontFace(family, `url(${url}) format('woff2')`, { style: 'normal', weight }); 51 | document.fonts.add(font); 52 | } 53 | loadFont('源暎アンチック', 'GenEiAntiqueNv5-M', '400'); 54 | loadFont('源暎エムゴ', 'GenEiMGothic2-Black', '700'); 55 | 56 | import { register } from 'swiper/element/bundle'; 57 | register(); 58 | 59 | import { assurePreferences } from "./preferences"; 60 | assurePreferences(); 61 | -------------------------------------------------------------------------------- /src/mascot/InlineDocument.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 |
16 |
{document.id}
17 |
{document.text}
18 |
19 | 20 | -------------------------------------------------------------------------------- /src/mascot/Mascot.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
{ 21 | $mascotWindowRect = new DOMRect(offsetX, offsetY, $mascotWindowRect.width, $mascotWindowRect.height); 22 | return `translate(${offsetX}px, ${offsetY}px)`; 23 | } 24 | }}> 25 |
26 | 27 |
28 | 29 | 30 |
31 | 32 | 33 |
34 |
35 | 36 | 70 | -------------------------------------------------------------------------------- /src/mascot/mascotStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | import type { Writable } from "svelte/store"; 3 | 4 | export const mascotVisible = writable(false); 5 | export const mascotWindowRect: Writable = writable(new DOMRect(0, 0, 500, 700)); 6 | -------------------------------------------------------------------------------- /src/mascot/servant.ts: -------------------------------------------------------------------------------- 1 | import type { Vector } from "../lib/layeredCanvas/tools/geometry/geometry"; 2 | import { Bubble } from "../lib/layeredCanvas/dataModels/bubble"; 3 | import { getHaiku } from "../lib/layeredCanvas/tools/haiku"; 4 | import type { Context } from "./servantContext"; 5 | 6 | type Parameters = { [key: string]: any }; 7 | 8 | function getPaperSize(context: Context) { 9 | return context.book.pages[context.pageIndex].paperSize; 10 | } 11 | 12 | export class AIError extends Error { 13 | constructor(message: string) { 14 | super(message); 15 | this.name = "AIError"; 16 | } 17 | } 18 | 19 | export class AIArgumentError extends AIError { 20 | constructor(message: string) { 21 | super(`引数の問題: ${message}`); 22 | this.name = "AIArgumentError"; 23 | } 24 | } 25 | 26 | type CreateBubbleArgs = { 27 | text: string; 28 | position: Vector; 29 | } 30 | 31 | function createBubble(context: Context, params: Parameters) { 32 | const args = params as CreateBubbleArgs; 33 | console.log("createBubble", args); 34 | if (args.text == null) { 35 | throw new AIArgumentError("テキストが空です"); 36 | } else if (args.text === "") { 37 | args.text = getHaiku(); 38 | } 39 | if (args.position == null || args.position.length !== 2 || 40 | typeof args.position[0] !== "number" || typeof args.position[1] !== "number") { 41 | throw new AIArgumentError("positionが不正です"); 42 | } 43 | const paperSize = getPaperSize(context); 44 | const bubble = new Bubble(); 45 | bubble.text = args.text; 46 | bubble.initOptions(); 47 | // bubble.forceEnoughSize(paperSize); 48 | bubble.setPhysicalCenter(paperSize, [paperSize[0] * args.position[0], paperSize[1] * args.position[1]]); 49 | const size = bubble.calculateFitSize(paperSize); 50 | bubble.setPhysicalSize(paperSize, size); 51 | console.log(bubble); 52 | context.book.pages[context.pageIndex].bubbles.push(bubble); 53 | } 54 | 55 | export type FunctionCalling = { 56 | tool: string; 57 | parameters: Parameters; 58 | } 59 | 60 | type Servant = (context: Context, parameters: Parameters) => void; 61 | 62 | // 関数の定義に基づいて関数を動的に呼び出す関数 63 | export function callServant(context: Context, funcalls: FunctionCalling[]) { 64 | const servants: { [key: string]: Servant } = { 65 | "createBubble": createBubble, 66 | } 67 | 68 | for (const funcall of funcalls) { 69 | const servant = servants[funcall.tool]; 70 | if (servant == null) { 71 | throw new AIError(`関数${funcall.tool}は存在しません`); 72 | } 73 | servant(context, funcall.parameters); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/mascot/servantContext.ts: -------------------------------------------------------------------------------- 1 | import type { Book } from "../lib/book/book" 2 | 3 | export type Context = { 4 | book: Book; 5 | pageIndex: number; 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /src/mascot/storyboard.ts: -------------------------------------------------------------------------------- 1 | export type Character = { name: string, appearance: string }; 2 | export type Bubble = { owner: string, speech: string }; 3 | export type Panel = { composition: string, bubbles: Bubble[] }; 4 | export type Page = { panels: Panel[] }; 5 | 6 | export type Storyboard = { 7 | format: "4koma" | "standard"; 8 | characters: Character[], 9 | pages: Page[] 10 | } 11 | -------------------------------------------------------------------------------- /src/materialBucket/materialBucketStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const materialBucketOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/notebook/AutoSizeTextarea.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/notebook/Notebook.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 | 26 | 27 | 28 |
29 | 30 | -------------------------------------------------------------------------------- /src/notebook/NotebookTextarea.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 | {#if waiting} 27 |
28 | 29 |
30 | {:else} 31 | 32 |
33 | 34 | 35 | カイルちゃん考えて! dispatch('advise', value)} use:toolTip={`カイルちゃん考えて![${cost}]`} /> 36 | 37 | 38 | クリップボードにコピー 39 |
40 | {/if} 41 |
42 | 43 | -------------------------------------------------------------------------------- /src/notebook/callAdvise.ts: -------------------------------------------------------------------------------- 1 | import { Notebook } from '../lib/book/notebook'; 2 | import { advise } from '../firebase'; 3 | import { onlineAccount, type OnlineAccount } from '../utils/accountStore'; 4 | 5 | export async function callAdvise(action: string, notebook: Notebook, instruction?: string): Promise { 6 | const result = await advise({action, notebook, instruction}); 7 | console.log(result); 8 | onlineAccount.update((x: OnlineAccount | null) => { 9 | if (!x) { return x; } 10 | x.feathral = result.feathral; return x; 11 | }); 12 | return result.result; 13 | } 14 | -------------------------------------------------------------------------------- /src/notebook/notebookStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const notebookOpen = writable(false); 4 | -------------------------------------------------------------------------------- /src/painter/FreehandInspectorEasing.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /src/painter/FreehandInspectorPalette.svelte: -------------------------------------------------------------------------------- 1 | 26 | 27 |
28 |
29 | 30 | 36 |
37 |
38 | {#each colors as c} 39 | 40 | 41 |
color = c} 47 | /> 48 | {/each} 49 |
50 |
51 | 52 | -------------------------------------------------------------------------------- /src/painter/FreehandInspectorTaper.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 | 14 |
15 |
16 | {#if taper.taper == 0} 17 | 20 | {:else} 21 |
22 | 23 |
24 | {/if} 25 |
26 | 27 | 34 | -------------------------------------------------------------------------------- /src/preferences.ts: -------------------------------------------------------------------------------- 1 | import { openDB, type IDBPDatabase } from 'idb'; 2 | 3 | const preferencesStores = ["imaging"]; 4 | const preferencesVersion = 1; 5 | 6 | let dbPromise: Promise>; 7 | 8 | export function assurePreferences() { 9 | dbPromise = openDB("preferences", preferencesVersion, { 10 | upgrade(db) { 11 | for (const store of preferencesStores) { 12 | db.createObjectStore(store); 13 | } 14 | } 15 | }); 16 | } 17 | 18 | export function getDBPromise() { 19 | return dbPromise; 20 | } 21 | 22 | export function createPreference(storeName: string, key: string) { 23 | let saved: T | undefined = undefined; 24 | return { 25 | get: async () => { 26 | saved = await (await dbPromise).get(storeName, key); 27 | console.log("preference get", saved); 28 | return saved; 29 | }, 30 | getOrDefault: async (defaultValue: T) => { 31 | saved = await (await dbPromise).get(storeName, key); 32 | if (saved === undefined) { 33 | saved = defaultValue; 34 | await (await dbPromise).put(storeName, defaultValue, key); 35 | } 36 | console.log("preference getOrDefault", saved); 37 | return saved; 38 | }, 39 | set: async (value: T) => { 40 | if (value !== saved) { 41 | saved = value; 42 | await (await dbPromise).put(storeName, value, key); 43 | console.log("preference set", value); 44 | } 45 | } 46 | }; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /src/rootelements/AboutButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/rootelements/BellButton.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/rootelements/CabinetButton.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/rootelements/DownloadButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/rootelements/MaterialBucketButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/rootelements/RulerButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/rootelements/SaveOffButton.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 | {#if $saveProhibitFlag} 18 | 22 | {:else} 23 | 27 | {/if} 28 | 29 | 43 | -------------------------------------------------------------------------------- /src/rootelements/VideoButton.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/t.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jonigata/FramePlanner2/2a1aa68a993c8bd45595d21548cc441e7f9c24ee/src/t.json -------------------------------------------------------------------------------- /src/toolbar/AvatarIcon.svelte: -------------------------------------------------------------------------------- 1 | 27 | 28 | 29 | 30 |
31 | {#if src || gravatarUrl} 32 | 33 | {:else} 34 | 35 | {initials} 36 | 37 | {/if} 38 |
39 | 40 | 47 | -------------------------------------------------------------------------------- /src/transfer/MangaFarmDialog.svelte: -------------------------------------------------------------------------------- 1 | 3 | 4 |
5 |

まんがファーム! オープン

6 |

7 | 新しいまんがコミュニケーションサイト「まんがファーム!」がオープンしました! 8 |

9 | manga farm 10 |

11 | FramePlannerは、「まんがファーム!」の1セクションとして再スタートしています。今まで通り無料、ログインなしで使えます! 12 |

13 |

14 | 旧サイト(このサイト、つまりhttps://frameplanner.online、https://frameplanner-e5569.web.app)は今後更新されませんので、お早めに移行をお願いします。 15 |

16 |

17 | 新サイトではすでに、動画埋め込み・フォルダパッケージ・高性能背景除去・アップスケーラー・ページ複製・名簿機能などの新機能を実装済みです。 18 |

19 |

20 | いまならプロファイル登録で500Spryt(サイト内通貨)、初投稿で500Sprytを貰えるので、AIまんが生成や動画生成で遊んでみてください! 21 |

22 |

23 | データ移行に関しては、旧サイト(ここ)のツールバーからデータのダンプ、新サイトのツールバーからデータのリストアが可能となっていますので、ぜひご活用ください。 24 |

25 |
26 | 27 | -------------------------------------------------------------------------------- /src/uiStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export type DominantMode = "standard" | "painting"; 4 | export const dominantMode = writable("standard"); 5 | -------------------------------------------------------------------------------- /src/undoStore.ts: -------------------------------------------------------------------------------- 1 | import { writable } from "svelte/store"; 2 | 3 | export const undoStore = writable(null); 4 | export const commitIfDirtyToken = writable(false); 5 | export const commitToken = writable(null); // tag 6 | -------------------------------------------------------------------------------- /src/utils/AutoSizeCanvas.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 | 26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /src/utils/Comic.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 | {#each pages as page} 11 | 12 | 13 | 14 | 15 | {/each} 16 | 17 | 18 |
19 | 20 | -------------------------------------------------------------------------------- /src/utils/DebugOnly.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | {#if $developmentFlag} 6 | 7 | {/if} 8 | -------------------------------------------------------------------------------- /src/utils/EmbeddedHtml.svelte: -------------------------------------------------------------------------------- 1 | 28 | 29 | {#key key} 30 | 37 | {/key} 38 | 39 | -------------------------------------------------------------------------------- /src/utils/ExponentialRangeSlider.svelte: -------------------------------------------------------------------------------- 1 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/utils/Feathral.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | feathral 10 | Feathral: {feathral} 11 |
12 | 13 | 19 | -------------------------------------------------------------------------------- /src/utils/FeathralCost.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | {#if showsLabel} 9 | 消費 10 | {/if} 11 | feathral 12 | x{cost} 13 | 14 | 15 | 21 | -------------------------------------------------------------------------------- /src/utils/FileBrowser.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |
8 |
9 |

使用中

10 | 11 |

リンク切れ

12 | 13 |
14 | 15 | 16 | 17 |
18 | 19 | -------------------------------------------------------------------------------- /src/utils/FullScreenLoading.svelte: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /src/utils/FullScreenProgress.svelte: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /src/utils/ImageViewer.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 | 22 | 23 | 24 | Viewer image 31 |
32 | 33 | -------------------------------------------------------------------------------- /src/utils/JsonReader.svelte: -------------------------------------------------------------------------------- 1 | 13 | 14 |
15 | 16 | 17 |
18 |
19 | {json} 20 |
21 |
22 | 23 |
24 | 25 | -------------------------------------------------------------------------------- /src/utils/Loading.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if $loading} 7 | 12 | {/if} 13 | 14 | 27 | -------------------------------------------------------------------------------- /src/utils/Parameter.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 |
21 | {label} 22 |
23 |
24 | 25 |
26 | 27 |
28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /src/utils/PassiveToolTip.svelte: -------------------------------------------------------------------------------- 1 | 38 | 39 |
46 |
47 | {#if $toolTipRequest} 48 | {$toolTipRequest.message} 49 | {#if $toolTipRequest.cost} 50 |
51 | 52 |
53 | {/if} 54 | {/if} 55 |
56 |
57 | 58 | 84 | -------------------------------------------------------------------------------- /src/utils/Progress.svelte: -------------------------------------------------------------------------------- 1 | 5 | 6 | {#if $progress != null} 7 | 12 | {/if} 13 | 14 | 30 | -------------------------------------------------------------------------------- /src/utils/SignIn.svelte: -------------------------------------------------------------------------------- 1 | 18 | 19 |
20 |
21 |
22 | {#if pending} 23 | ログイン処理中…… 24 | {/if} 25 |
26 |
27 |
28 | 29 | 30 | {#if !pending} 31 | 32 | {/if} 33 |
34 | 35 | -------------------------------------------------------------------------------- /src/utils/SliderEdit.svelte: -------------------------------------------------------------------------------- 1 | 11 | 12 |
13 |
{label}
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 | -------------------------------------------------------------------------------- /src/utils/SpreadCanvas.svelte: -------------------------------------------------------------------------------- 1 | 45 | 46 |
47 |
48 | 49 |
50 |
51 | 52 | -------------------------------------------------------------------------------- /src/utils/Spreader.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 |
33 | 34 | 35 |
36 | -------------------------------------------------------------------------------- /src/utils/TreeView.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
    18 |
  • 19 | {#if tree.children && tree.children.length > 0} 20 | 21 | 22 | 23 | 24 | {tree.label} 25 | 26 | {#if expanded} 27 | {#each tree.children as child} 28 | 29 | {/each} 30 | {/if} 31 | {:else} 32 | 33 | 34 | {tree.label} 35 | 36 | {/if} 37 |
  • 38 |
39 | 40 | 55 | -------------------------------------------------------------------------------- /src/utils/ads/AdContainer.svelte: -------------------------------------------------------------------------------- 1 | 22 | 23 |
24 |
25 | 26 |
27 | 28 |
29 |
30 | 41 |
42 |
43 | 44 | 50 | -------------------------------------------------------------------------------- /src/utils/ads/AdPanel.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 |
24 |
28 | 29 | 30 |
31 |
32 |
33 | 34 | 43 | -------------------------------------------------------------------------------- /src/utils/asyncStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, derived, get } from "svelte/store"; 2 | 3 | type AsyncStoreActions = { 4 | subscribe: (run: (value: AsyncStoreState) => void) => () => void; 5 | trigger: () => Promise; 6 | resolve: (value: T) => void; 7 | isActive: {subscribe: (run: (value: boolean) => void) => () => void }; 8 | }; 9 | 10 | type AsyncStoreState = { 11 | isActive: boolean; 12 | resolve: ((value: T) => void) | null; 13 | }; 14 | 15 | export function createAsyncStore(): AsyncStoreActions { 16 | const store = writable>({ isActive: false, resolve: null }); 17 | 18 | const isActive = derived(store, $store => $store.isActive); 19 | 20 | function trigger(): Promise { 21 | return new Promise((resolve) => { 22 | store.set({ isActive: true, resolve }); 23 | }); 24 | } 25 | 26 | function resolve(value: T) { 27 | const currentState = get(store); 28 | if (currentState.resolve) { 29 | currentState.resolve(value); 30 | store.set({ isActive: false, resolve: null }); // 自動的にisActiveをfalseに設定 31 | } 32 | } 33 | 34 | return { 35 | subscribe: store.subscribe, 36 | trigger, 37 | resolve, 38 | isActive 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/backUpIndexedDB.ts: -------------------------------------------------------------------------------- 1 | type DataCopy = { [storeName: string]: any[] }; 2 | 3 | export const copyIndexedDB = (dbName: string): Promise => { 4 | return new Promise((resolve, reject) => { 5 | const request = indexedDB.open(dbName); 6 | let db: IDBDatabase | null = null; 7 | 8 | request.onsuccess = (event: Event) => { 9 | db = (event.target as IDBOpenDBRequest).result; 10 | const dataCopy: DataCopy = {}; 11 | 12 | const transaction = db.transaction(db.objectStoreNames, "readonly"); 13 | transaction.oncomplete = () => { 14 | resolve(dataCopy); 15 | }; 16 | transaction.onerror = (event) => reject(event); 17 | 18 | Array.from(db.objectStoreNames).forEach((storeName) => { 19 | const store = transaction.objectStore(storeName); 20 | const query = store.getAll(); 21 | 22 | query.onsuccess = () => { 23 | dataCopy[storeName] = query.result; 24 | }; 25 | }); 26 | }; 27 | 28 | request.onerror = (event) => { 29 | reject((event.target as IDBRequest).error); 30 | }; 31 | }); 32 | }; 33 | 34 | 35 | export const restoreIndexedDB = (dbName: string, dataCopy: DataCopy): Promise => { 36 | return new Promise((resolve, reject) => { 37 | const request = indexedDB.open(dbName); 38 | 39 | request.onupgradeneeded = (event: IDBVersionChangeEvent) => { 40 | // Create object stores if they don't exist, based on dataCopy keys 41 | let db = (event.target as IDBOpenDBRequest).result; 42 | Object.keys(dataCopy).forEach((storeName) => { 43 | if (!db.objectStoreNames.contains(storeName)) { 44 | db.createObjectStore(storeName); 45 | } 46 | }); 47 | }; 48 | 49 | request.onsuccess = (event: Event) => { 50 | const db = (event.target as IDBOpenDBRequest).result; 51 | const transaction = db.transaction(db.objectStoreNames, "readwrite"); 52 | 53 | transaction.oncomplete = () => resolve(); 54 | transaction.onerror = (event) => reject(event); 55 | 56 | Object.entries(dataCopy).forEach(([storeName, records]) => { 57 | const store = transaction.objectStore(storeName); 58 | // Clear existing entries to avoid duplicates 59 | store.clear(); 60 | records.forEach((record) => { 61 | store.add(record); 62 | }); 63 | }); 64 | }; 65 | 66 | request.onerror = (event) => { 67 | reject((event.target as IDBRequest).error); 68 | }; 69 | }); 70 | }; 71 | -------------------------------------------------------------------------------- /src/utils/bookArchiverStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | 3 | export type BookArchiveOperation = 4 | 'download' | 5 | 'copy' | 6 | 'export-psd' | 7 | 'aipictors' | 8 | 'envelope' | 9 | 'export-prompts' | 10 | 'publish' | 11 | 'share-book'; 12 | 13 | export const bookArchiver: Writable = writable([]); 14 | -------------------------------------------------------------------------------- /src/utils/colorpicker/ColorPickerLabel.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 |
22 |
23 |
24 |
25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /src/utils/colorpicker/colorPickerStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store" 2 | 3 | export type ColorPickerCall = { 4 | position: {x: number, y: number}; 5 | color: string; 6 | onUpdate: (color: string) => void; 7 | } 8 | 9 | export const colorPickerStore: Writable = writable(null); 10 | -------------------------------------------------------------------------------- /src/utils/delayedCommiter.ts: -------------------------------------------------------------------------------- 1 | export class DelayedCommiter { 2 | when: number; 3 | timerId: number | null; 4 | commit: () => void; 5 | 6 | constructor(commit: () => void) { 7 | this.when = 0; 8 | this.timerId = null; 9 | this.commit = commit; 10 | } 11 | 12 | schedule(ms: number) { 13 | // 未来の方を選ぶ 14 | const newWhen = Date.now() + ms; 15 | if (this.when < newWhen) { 16 | if (this.timerId !== null) { 17 | clearTimeout(this.timerId); 18 | } 19 | this.when = newWhen; 20 | this.timerId = window.setTimeout(() => { 21 | this.commit(); 22 | this.when = 0; 23 | this.timerId = null; 24 | }, ms); 25 | } 26 | } 27 | 28 | cancel() { 29 | if (this.timerId !== null) { 30 | clearTimeout(this.timerId); 31 | this.when = 0; 32 | this.timerId = null; 33 | } 34 | } 35 | 36 | force() { 37 | if (this.timerId !== null) { 38 | clearTimeout(this.timerId); 39 | this.when = 0; 40 | this.timerId = null; 41 | this.commit(); 42 | } 43 | } 44 | } 45 | 46 | export class DelayedCommiterGroup { 47 | commiters: { [key: string]: DelayedCommiter }; 48 | currentTag: string | null = null; 49 | 50 | constructor( commiters: { [key: string]: () => void }) { 51 | this.commiters = {}; 52 | for (const key in commiters) { 53 | this.commiters[key] = new DelayedCommiter(commiters[key]); 54 | } 55 | } 56 | 57 | schedule(key: string, ms: number) { 58 | if (this.currentTag !== key) { 59 | this.force(); 60 | } 61 | this.commiters[key].schedule(ms); 62 | this.currentTag = key; 63 | } 64 | 65 | cancel() { 66 | for (const key in this.commiters) { 67 | this.commiters[key].cancel(); 68 | } 69 | } 70 | 71 | force() { 72 | for (const key in this.commiters) { 73 | this.commiters[key].force(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /src/utils/developmentFlagStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, get } from "svelte/store"; 2 | 3 | export const developmentFlag = writable(false); 4 | export const saveProhibitFlag = writable(false); 5 | 6 | // localhostか127.0.0.1だったら 7 | developmentFlag.set(location.hostname === "localhost" || location.hostname === "127.0.0.1"); 8 | console.log("================ developmentFlag", get(developmentFlag)); 9 | -------------------------------------------------------------------------------- /src/utils/dropzone.ts: -------------------------------------------------------------------------------- 1 | // src/actions/dropzone.ts 2 | type DropHandler = (files: FileList) => void; 3 | 4 | export function dropzone(node: HTMLElement, onDrop: DropHandler) { 5 | const handleDragOver = (event: DragEvent) => { 6 | event.preventDefault(); 7 | node.classList.add('drag-over'); 8 | }; 9 | 10 | const handleDragLeave = (event: DragEvent) => { 11 | node.classList.remove('drag-over'); 12 | }; 13 | 14 | const handleDrop = (event: DragEvent) => { 15 | event.preventDefault(); 16 | node.classList.remove('drag-over'); 17 | if (event.dataTransfer) { 18 | const files = event.dataTransfer.files; 19 | if (files.length > 0) { 20 | onDrop(files); // 引数で渡された関数を実行 21 | } 22 | } 23 | }; 24 | 25 | node.addEventListener('dragover', handleDragOver); 26 | node.addEventListener('dragleave', handleDragLeave); 27 | node.addEventListener('drop', handleDrop); 28 | 29 | return { 30 | destroy() { 31 | node.removeEventListener('dragover', handleDragOver); 32 | node.removeEventListener('dragleave', handleDragLeave); 33 | node.removeEventListener('drop', handleDrop); 34 | } 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/utils/effectprocessor/effectProcessorStore.ts: -------------------------------------------------------------------------------- 1 | import type { Film } from "../../lib/layeredCanvas/dataModels/film"; 2 | import { redrawToken } from "../../bookeditor/bookStore"; 3 | import { PubSubQueue } from "../pubsub"; 4 | 5 | export const effectProcessorQueue = new PubSubQueue(); 6 | effectProcessorQueue.subscribe(async (film: Film) => { 7 | let inputMedia = film.media; 8 | for (const effect of film.effects) { 9 | inputMedia = await effect.apply(inputMedia); 10 | } 11 | redrawToken.set(true); 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /src/utils/executeProcessAndNotify.ts: -------------------------------------------------------------------------------- 1 | import { toastStore } from '@skeletonlabs/skeleton'; 2 | 3 | export async function executeProcessAndNotify( 4 | thresholdMillisecs: number, 5 | notificationMessage: string, 6 | asyncProcess: () => Promise 7 | ): Promise { 8 | const granted = await requestNotificationPermission(); 9 | try { 10 | const start = new Date(); 11 | const result = await asyncProcess(); 12 | const timeouts = thresholdMillisecs < (new Date().getTime() - start.getTime()); 13 | if (granted) { 14 | sendNotification(notificationMessage, timeouts); 15 | } 16 | return result; 17 | } catch (error) { 18 | console.error("プロセス実行中にエラーが発生しました: ", error); 19 | throw error; 20 | } 21 | } 22 | 23 | async function requestNotificationPermission(): Promise { 24 | if (!("Notification" in window)) return false; 25 | if (Notification.permission === "granted") return true; 26 | if (Notification.permission === "denied") return false; 27 | 28 | const permission = await Notification.requestPermission(); 29 | return permission === "granted"; 30 | } 31 | 32 | function sendNotification(message: string, timeouts: boolean) { 33 | if (document.visibilityState === 'visible' || !timeouts) { 34 | toastStore.trigger({ message, timeout: 3000 }); 35 | } else { 36 | const n = new Notification(message); 37 | n.onclick = () => { 38 | window.focus(); 39 | n.close(); 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/utils/fileBrowserStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, type Writable } from "svelte/store"; 2 | 3 | export const browserUsedImages: Writable = writable([]); 4 | export const browserStrayImages: Writable= writable([]); 5 | -------------------------------------------------------------------------------- /src/utils/hoverKeyStore.ts: -------------------------------------------------------------------------------- 1 | export function hoverKey(node: HTMLElement, onKeyDown: (event: KeyboardEvent) => void) { 2 | const handleMouseEnter = (event: MouseEvent) => { 3 | document.addEventListener("keydown", onKeyDown); 4 | } 5 | const handleMouseLeave = (event: MouseEvent) => { 6 | document.removeEventListener("keydown", onKeyDown); 7 | } 8 | 9 | node.addEventListener("mouseenter", handleMouseEnter); 10 | node.addEventListener("mouseleave", handleMouseLeave); 11 | 12 | return { 13 | destroy() { 14 | node.removeEventListener("mouseenter", handleMouseEnter); 15 | node.removeEventListener("mouseleave", handleMouseLeave); 16 | document.removeEventListener("keydown", onKeyDown); 17 | } 18 | }; 19 | } -------------------------------------------------------------------------------- /src/utils/imageViewerStore.ts: -------------------------------------------------------------------------------- 1 | import { type Writable, writable } from "svelte/store"; 2 | 3 | export const imageViewerTarget: Writable = writable(null); 4 | -------------------------------------------------------------------------------- /src/utils/loadingStore.ts: -------------------------------------------------------------------------------- 1 | import { writable, type Writable } from "svelte/store"; 2 | 3 | export const loading = writable(false); 4 | export const progress: Writable = writable(null); 5 | -------------------------------------------------------------------------------- /src/utils/moveInArray.ts: -------------------------------------------------------------------------------- 1 | export function moveInArray(a: T[], oldIndex: number, newIndex: number) { 2 | // console.log("moveInArray", (a as any).map(e => e.index), oldIndex, newIndex); 3 | a.splice(newIndex, 0, a.splice(oldIndex, 1)[0]); 4 | } 5 | -------------------------------------------------------------------------------- /src/utils/observeResize.ts: -------------------------------------------------------------------------------- 1 | import type { Writable } from 'svelte/store'; 2 | import { get } from 'svelte/store'; 3 | 4 | export function resize(node: HTMLElement, store: Writable) { 5 | const r = get(store); 6 | node.style.width = r.width + 'px'; 7 | node.style.height = r.height + 'px'; 8 | node.style.left = r.x + 'px'; 9 | node.style.top = r.y + 'px'; 10 | 11 | const observer = new ResizeObserver(entries => { 12 | const r = get(store); 13 | store.set(new DOMRect(r.x, r.y, entries[0].contentRect.width, entries[0].contentRect.height)); 14 | }); 15 | 16 | observer.observe(node); 17 | 18 | return { 19 | destroy() { 20 | observer.disconnect(); 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/utils/observeWithin.ts: -------------------------------------------------------------------------------- 1 | export function fitWithin(node: HTMLElement) { 2 | const observer = new IntersectionObserver(entries => { 3 | for (const entry of entries) { 4 | if (!entry.isIntersecting) { 5 | const rect = node.getBoundingClientRect(); 6 | const parentRect = node.parentElement!.getBoundingClientRect(); 7 | 8 | if (rect.bottom > parentRect.bottom) { 9 | node.style.top = `${parentRect.bottom - rect.height}px`; 10 | } 11 | if (rect.right > parentRect.right) { 12 | node.style.left = `${parentRect.right - rect.width}px`; 13 | } 14 | if (rect.top < parentRect.top) { 15 | node.style.top = `0px`; 16 | } 17 | if (rect.left < parentRect.left) { 18 | node.style.left = `0px`; 19 | } 20 | } 21 | } 22 | }, { 23 | threshold: 1.0 24 | }); 25 | 26 | observer.observe(node); 27 | 28 | return { 29 | destroy() { 30 | observer.disconnect(); 31 | } 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/utils/persistentText.ts: -------------------------------------------------------------------------------- 1 | import { createPreference } from '../preferences'; 2 | 3 | interface PersistentOptions { 4 | store: string; 5 | key: string; 6 | onLoad?: (value: string) => void; 7 | } 8 | 9 | export function persistentText(node: HTMLElement, options: PersistentOptions) { 10 | const { store, key, onLoad } = options; 11 | 12 | const preference = createPreference(store, key); 13 | 14 | async function load() { 15 | const value = await preference.get(); 16 | if (value) { 17 | if (onLoad) { 18 | onLoad(value); 19 | } 20 | if (node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement) { 21 | node.value = value; 22 | } else { 23 | node.textContent = value; 24 | } 25 | } 26 | } 27 | 28 | async function save(value: string) { 29 | await preference.set(value); 30 | } 31 | 32 | function onInput() { 33 | const value = node instanceof HTMLInputElement || node instanceof HTMLTextAreaElement 34 | ? node.value 35 | : node.textContent || ''; 36 | save(value); 37 | } 38 | 39 | node.addEventListener('input', onInput); 40 | load(); // 初期ロード 41 | 42 | return { 43 | update(newOptions: PersistentOptions) { 44 | Object.assign(options, newOptions); 45 | }, 46 | destroy() { 47 | node.removeEventListener('input', onInput); 48 | } 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /src/utils/punchFilm.ts: -------------------------------------------------------------------------------- 1 | import { ImageMedia } from '../lib/layeredCanvas/dataModels/media'; 2 | import { Film } from '../lib/layeredCanvas/dataModels/film'; 3 | import { removeBg } from "../firebase"; 4 | import { createCanvasFromImage } from "../lib/layeredCanvas/tools/imageUtil"; 5 | import { getAnalytics, logEvent } from "firebase/analytics"; 6 | 7 | export async function punchFilm(film: Film) { 8 | const imageMedia = film.media as ImageMedia; 9 | if (!(imageMedia instanceof ImageMedia)) { return; } 10 | 11 | const dataUrl = imageMedia.canvas.toDataURL("image/png"); 12 | const r = await removeBg(dataUrl); 13 | 14 | const image = document.createElement('img'); 15 | image.src = "data:image/png;base64," + r.result.image; 16 | await image.decode(); 17 | 18 | const canvas = createCanvasFromImage(image); 19 | film.media = new ImageMedia(canvas); 20 | 21 | logEvent(getAnalytics(), 'punch'); 22 | } 23 | -------------------------------------------------------------------------------- /src/utils/reactUtil.ts: -------------------------------------------------------------------------------- 1 | import { type Writable } from 'svelte/store'; 2 | 3 | export function waitForChange(store: Writable, condition: (value: T) => boolean): Promise { 4 | return new Promise((resolve) => { 5 | const unsubscribe = store.subscribe(value => { 6 | if (condition(value)) { 7 | unsubscribe(); 8 | resolve(value); 9 | } 10 | }); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /src/utils/saver/copyToClipboard.ts: -------------------------------------------------------------------------------- 1 | import type { Page } from '../../lib/book/book'; 2 | import { renderPageToBlob } from './renderPage'; 3 | 4 | export async function copyToClipboard(page: Page) { 5 | try { 6 | // CanvasをBlobとして取得する 7 | const blob = await renderPageToBlob(page); 8 | 9 | if (blob) { 10 | // BlobをClipboardItemとしてクリップボードに書き込む 11 | await navigator.clipboard.write([ 12 | new ClipboardItem({[blob.type]: blob}), 13 | ]); 14 | console.log(`Canvas content copied to clipboard. ${blob.type}`); 15 | } else { 16 | console.error("Failed to copy canvas content to clipboard: Blob is null."); 17 | } 18 | } catch (err) { 19 | console.error("Failed to copy canvas content to clipboard:", err); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/utils/saver/exportPrompts.ts: -------------------------------------------------------------------------------- 1 | import { collectLeaves } from '../../lib/layeredCanvas/dataModels/frameTree'; 2 | import type { Page } from '../../lib/book/book'; 3 | 4 | export async function exportPrompts(pages: Page[]) { 5 | const prompts = []; 6 | for (let i = 0; i < pages.length; i++) { 7 | const leaves = collectLeaves(pages[i].frameTree); 8 | for (const leaf of leaves) { 9 | prompts.push(leaf.prompt); 10 | } 11 | } 12 | const blob = new Blob([prompts.join('\n')], {type: 'text/plain'}); 13 | await navigator.clipboard.write([ 14 | new ClipboardItem({[blob.type]: blob}), 15 | ]); 16 | } 17 | -------------------------------------------------------------------------------- /src/utils/saver/postToAiPictors.ts: -------------------------------------------------------------------------------- 1 | import type { Page } from '../../lib/book/book'; 2 | import { renderPageToBlob, renderPageToDataUrl } from './renderPage'; 3 | 4 | export async function postToAiPictors(page: Page): Promise { 5 | const dataUrl = await renderPageToDataUrl(page); 6 | const blob = new Blob([dataUrl], { type: "text/plain" }); 7 | const formData = new FormData(); 8 | formData.append("imageData", blob); 9 | 10 | const response = await fetch( 11 | "https://www.aipictors.com/wp-content/themes/AISite/post-img-cache.php", 12 | { 13 | method: 'POST', 14 | body: formData 15 | }); 16 | 17 | console.log("postToAiPictors:2"); 18 | if (response.ok) { 19 | console.log("postToAiPictors:3"); 20 | const data = await response.json(); 21 | console.log(data); 22 | if (data.result === "success") { 23 | console.log("postToAiPictors:4"); 24 | const nanoid = data.nanoid; 25 | console.log("nanoid:", nanoid); 26 | const newTabUrl = `https://www.aipictors.com/post/?cache=${nanoid}`; 27 | window.open(newTabUrl, "_blank"); 28 | } else if (data.result === "oversize") { 29 | throw "画像サイズが大きいです。"; 30 | } else if (data.result === "noimage") { 31 | throw "空の画像が送信されました。"; 32 | } else { 33 | throw "エラーが発生しました。"; 34 | } 35 | console.log("postToAiPictors:5"); 36 | } else { 37 | throw "リクエストが失敗しました。"; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/utils/saver/saveAsPng.ts: -------------------------------------------------------------------------------- 1 | import { saveAs } from 'file-saver'; 2 | import type { Page } from '../../lib/book/book'; 3 | import { renderPageToBlob } from './renderPage'; 4 | 5 | export async function saveAsPng(page: Page) { 6 | const png = await renderPageToBlob(page); 7 | saveAs(png, 'comic.png'); 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/saver/saveAsPsd.ts: -------------------------------------------------------------------------------- 1 | import { saveAs } from 'file-saver'; 2 | import type { Page } from '../../lib/book/book'; 3 | import { renderPageToPsd } from './renderPage'; 4 | 5 | export async function saveAsPsd(page: Page) { 6 | const psd = await renderPageToPsd(page); 7 | saveAs(psd, 'comic.psd'); 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/saver/saveAsZip.ts: -------------------------------------------------------------------------------- 1 | import { saveAs } from 'file-saver'; 2 | import JSZip from 'jszip'; 3 | import type { Page } from '../../lib/book/book'; 4 | import { renderPageToBlob, renderPageToPsd } from './renderPage'; 5 | 6 | export async function makeZip(pages: Page[], render: (page: Page) => Promise, ext: string): Promise { 7 | const zip = new JSZip(); 8 | const folder = zip.folder('book')!; 9 | 10 | for (let i = 0; i < pages.length; i++) { 11 | const pic = await render(pages[i]); 12 | folder.file(`page-${i+1}.${ext}`, pic); 13 | } 14 | 15 | const zipFile = await zip.generateAsync({type: 'blob'}); 16 | return zipFile; 17 | } 18 | 19 | export async function saveAsPngZip(pages: Page[]) { 20 | const zipFile = await makeZip(pages, renderPageToBlob, 'png'); 21 | saveAs(zipFile, `book.zip`); 22 | } 23 | 24 | export async function saveAsPsdZip(pages: Page[]) { 25 | const zipFile = await makeZip(pages, renderPageToPsd, 'psd'); 26 | saveAs(zipFile, `book.psd.zip`); 27 | } -------------------------------------------------------------------------------- /src/utils/selection.ts: -------------------------------------------------------------------------------- 1 | export type SelectionInfo = { 2 | selectedText: string; 3 | node: HTMLTextAreaElement | HTMLInputElement; 4 | start: number; 5 | end: number; 6 | hasSelection: boolean; 7 | }; 8 | 9 | type SelectionCallback = (info: SelectionInfo) => void; 10 | 11 | type SelectionActionReturn = { 12 | destroy: () => void; 13 | }; 14 | 15 | export function selection( 16 | node: HTMLTextAreaElement | HTMLInputElement, 17 | callback: SelectionCallback 18 | ): SelectionActionReturn { 19 | const handleSelection = () => { 20 | const start = node.selectionStart ?? 0; 21 | const end = node.selectionEnd ?? 0; 22 | const hasSelection = start !== end; 23 | 24 | const info: SelectionInfo = { 25 | selectedText: hasSelection ? node.value.substring(start, end) : '', 26 | node, 27 | start, 28 | end, 29 | hasSelection 30 | }; 31 | 32 | callback(info); 33 | }; 34 | 35 | node.addEventListener('selectionchange', handleSelection); 36 | 37 | return { 38 | destroy() { 39 | node.removeEventListener('selectionchange', handleSelection); 40 | } 41 | }; 42 | } -------------------------------------------------------------------------------- /src/utils/sortableList.ts: -------------------------------------------------------------------------------- 1 | import Sortable from 'sortablejs'; 2 | import type { Options } from 'sortablejs'; 3 | 4 | export type { SortableEvent } from 'sortablejs'; 5 | 6 | export function sortableList(node: HTMLElement, options: Partial = {}) { 7 | let sortableInstance: Sortable; 8 | 9 | function createSortable() { 10 | sortableInstance = new Sortable(node, options); 11 | } 12 | 13 | function destroySortable() { 14 | if (sortableInstance) { 15 | sortableInstance.destroy(); 16 | } 17 | } 18 | 19 | createSortable(); 20 | 21 | return { 22 | update(newOptions: Partial) { 23 | destroySortable(); 24 | options = { ...options, ...newOptions }; 25 | createSortable(); 26 | }, 27 | destroy() { 28 | destroySortable(); 29 | } 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/waitDialog.ts: -------------------------------------------------------------------------------- 1 | import { type ModalSettings, modalStore } from '@skeletonlabs/skeleton'; 2 | 3 | export async function waitDialog(dialogComponent: string): Promise { 4 | const r = await new Promise((resolve) => { 5 | const d: ModalSettings = { 6 | type: 'component', 7 | component: dialogComponent, 8 | response: resolve, 9 | }; 10 | modalStore.trigger(d); 11 | }); 12 | return r; 13 | } 14 | -------------------------------------------------------------------------------- /src/videomaker/FrameResidenceTime.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 |
33 |
34 | Frame {index} 35 |
36 |
37 | 38 |
39 | 40 |
41 |
42 |
43 | 44 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /src/weaver/storyboard.ts: -------------------------------------------------------------------------------- 1 | export type Character = { name: string, appearance: string }; 2 | export type Bubble = { owner: string, speech: string }; 3 | export type Panel = { composition: string, bubbles: Bubble[] }; 4 | export type Page = { panels: Panel[] }; 5 | 6 | export type Storyboard = { 7 | format: "4koma" | "standard"; 8 | characters: Character[], 9 | pages: Page[] 10 | } 11 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | import preprocess from "svelte-preprocess"; 2 | import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; 3 | 4 | export default { 5 | // Consult https://svelte.dev/docs#compile-time-svelte-preprocess 6 | // for more information about preprocessors 7 | preprocess: [ 8 | vitePreprocess(), 9 | preprocess({ 10 | postcss: true, 11 | }), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | // 1. Apply the dark mode class setting: 4 | darkMode: 'class', 5 | content: [ 6 | './src/**/*.{html,js,svelte,ts}', 7 | // 2. Append the path for the Skeleton NPM package and files: 8 | require('path').join(require.resolve( 9 | '@skeletonlabs/skeleton'), 10 | '../**/*.{html,js,svelte,ts}' 11 | ) 12 | ], 13 | theme: { 14 | extend: {}, 15 | }, 16 | plugins: [ 17 | // 3. Append the Skeleton plugin to the end of this list 18 | ...require('@skeletonlabs/skeleton/tailwind/skeleton.cjs')() 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /test/setup.ts: -------------------------------------------------------------------------------- 1 | import 'fake-indexeddb/auto'; 2 | 3 | declare global { 4 | export interface Console { 5 | tag(tag: string, ...args: any[]): void; 6 | snapshot(obj: any): void; 7 | } 8 | } 9 | 10 | console.tag = function(tag, color, ...args) { 11 | // console.log(`%c${tag}`, `color:white; background-color:${color}; padding:2px 4px; border-radius:4px;`, ...args); 12 | // console.trace(); 13 | } 14 | 15 | if (!HTMLImageElement.prototype.decode) { 16 | HTMLImageElement.prototype.decode = async function () { 17 | return Promise.resolve(); 18 | }; 19 | } 20 | 21 | HTMLCanvasElement.prototype.getContext = function (contextId: '2d' | 'bitmaprenderer' | 'webgl' | 'webgl2', options?: any): CanvasRenderingContext2D | ImageBitmapRenderingContext | WebGLRenderingContext | null { 22 | if (contextId === '2d') { 23 | return { 24 | canvas: this, 25 | fillRect: () => {}, 26 | getContextAttributes: () => ({}), 27 | getImageData: () => ({ data: new Uint8ClampedArray() }), 28 | putImageData: () => {}, 29 | drawImage: () => {}, 30 | globalAlpha: 1.0, 31 | globalCompositeOperation: 'source-over', 32 | // Add other properties and methods as needed 33 | } as unknown as CanvasRenderingContext2D; 34 | } else if (contextId === 'bitmaprenderer') { 35 | return { 36 | canvas: this, 37 | transferFromImageBitmap: (bitmap: ImageBitmap | null) => {} 38 | } as unknown as ImageBitmapRenderingContext; 39 | } else if (contextId === 'webgl' || contextId === 'webgl2') { 40 | return { 41 | canvas: this, 42 | // Add WebGLRenderingContext properties and methods as needed 43 | } as unknown as WebGLRenderingContext; 44 | } 45 | return null; 46 | } as any; 47 | 48 | if (!URL.createObjectURL) { 49 | let counter = 0; 50 | URL.createObjectURL = () => `blob:dummy-url-${counter++}`; 51 | } 52 | 53 | if (!URL.revokeObjectURL) { 54 | URL.revokeObjectURL = () => {}; 55 | } 56 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "resolveJsonModule": true, 8 | "moduleResolution": "node", 9 | "esModuleInterop": true, 10 | /** 11 | * Typecheck JS in `.svelte` and `.js` files by default. 12 | * Disable checkJs if you'd like to use dynamic types in JS. 13 | * Note that setting allowJs false does not prevent the use 14 | * of JS in `.svelte` files. 15 | */ 16 | "allowJs": true, 17 | "checkJs": true, 18 | "outDir": "./dist", 19 | "isolatedModules": true, 20 | }, 21 | "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", ], 22 | "references": [{ "path": "./tsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.svelte-check.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/svelte/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "resolveJsonModule": true, 8 | /** 9 | * Typecheck JS in `.svelte` and `.js` files by default. 10 | * Disable checkJs if you'd like to use dynamic types in JS. 11 | * Note that setting allowJs false does not prevent the use 12 | * of JS in `.svelte` files. 13 | */ 14 | "allowJs": true, 15 | "checkJs": false, 16 | "isolatedModules": true, 17 | }, 18 | "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", ], 19 | "references": [{ "path": "./tsconfig.node.json" }] 20 | } 21 | -------------------------------------------------------------------------------- /viewer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | まんがファーム! 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config' 2 | import { svelte } from '@sveltejs/vite-plugin-svelte' 3 | import { resolve } from 'path' 4 | import { glob } from 'glob' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | build: { 9 | minify: false, 10 | rollupOptions: { 11 | input: { 12 | main: resolve(__dirname, 'index.html'), 13 | ...Object.fromEntries( 14 | glob.sync('ads/**/index.html').map(file => [ 15 | file.slice(0, -11), // remove '/index.html' 16 | resolve(__dirname, file) 17 | ]) 18 | ) 19 | } 20 | }, 21 | outDir: 'dist' 22 | }, 23 | plugins: [svelte()], 24 | optimizeDeps: { 25 | include: ['paper'], 26 | }, 27 | server: { 28 | port: 5173, 29 | proxy: { 30 | '^/farm/?$': { 31 | target: 'http://localhost:5173', 32 | rewrite: (path) => '/farm.html', 33 | }, 34 | '^/farm/user/(.*)': { 35 | target: 'http://localhost:5173', 36 | rewrite: (path) => '/farm.html', 37 | }, 38 | '^/viewer/(.*)': { 39 | target: 'http://localhost:5001', 40 | rewrite: (path) => `/frameplanner-e5569/us-central1/socialcard/${path.split('/').pop()}`, 41 | } 42 | } 43 | }, 44 | test: { 45 | globals: true, 46 | environment: 'jsdom', 47 | include: ['src/**/*.{test,spec,vitest}.{js,ts}'], 48 | setupFiles: ['./test/setup.ts'], 49 | }, 50 | }) 51 | --------------------------------------------------------------------------------