├── .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 |
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 |

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 |
33 |
34 |
45 |
--------------------------------------------------------------------------------
/src/filemanager/FileManagerInsertZone.svelte:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
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 |
54 | {/if}
55 |
56 |
57 |
70 |
71 |
--------------------------------------------------------------------------------
/src/generator/Gallery.svelte:
--------------------------------------------------------------------------------
1 |
32 |
33 |
34 | {#each canvases as canvas}
35 |
36 | {/each}
37 |
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 |
15 |
16 | {#if imageProgress !== null}
17 |
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 |
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 |
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 |

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 |
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 |

10 |
Feathral: {feathral}
11 |
12 |
13 |
19 |
--------------------------------------------------------------------------------
/src/utils/FeathralCost.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | {#if showsLabel}
9 | 消費
10 | {/if}
11 |
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 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/utils/PassiveToolTip.svelte:
--------------------------------------------------------------------------------
1 |
38 |
39 |
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 |
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 |
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 |
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 |
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 |
--------------------------------------------------------------------------------