├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── CHANGES.md
├── KNOWN_ISSUES.md
├── LICENSE
├── README.md
├── assets
├── .gitkeep
├── blank.p
├── default
│ ├── default.atlas
│ └── default.png
├── demolition.p
├── explosion.p
├── firework.p
├── flame.p
├── glitch.p
├── infinity.p
├── laser.p
├── logo.png
├── particle-ball1.png
├── particle-ball2.png
├── particle-ball3.png
├── particle-ball4.png
├── particle-cloud.png
├── particle-fire.png
├── particle-star.png
├── particle.png
├── pre_particle.png
├── rain.p
├── skin
│ ├── bold.fnt
│ ├── boldx1_5.fnt
│ ├── boldx2.fnt
│ ├── boldx3.fnt
│ ├── boldx4.fnt
│ ├── font-black.fnt
│ ├── font-blackx1_5.fnt
│ ├── font-blackx2.fnt
│ ├── font-blackx3.fnt
│ ├── font-blackx4.fnt
│ ├── font.fnt
│ ├── fontx1_5.fnt
│ ├── fontx2.fnt
│ ├── fontx3.fnt
│ ├── fontx4.fnt
│ ├── gdxparticleeditor.atlas
│ ├── gdxparticleeditor.json
│ ├── gdxparticleeditor.png
│ ├── header.fnt
│ ├── headerx1_5.fnt
│ ├── headerx2.fnt
│ ├── headerx3.fnt
│ ├── headerx4.fnt
│ ├── high-contrast.fnt
│ ├── high-contrastx1_5.fnt
│ ├── high-contrastx2.fnt
│ ├── high-contrastx3.fnt
│ └── high-contrastx4.fnt
├── smoke.p
├── sparks.p
├── splash.p
├── thruster.p
└── trail.p
├── build.gradle
├── core
├── build.gradle
├── icons
│ ├── logo.icns
│ ├── logo.ico
│ └── logo.png
└── src
│ └── main
│ ├── java
│ └── com
│ │ ├── badlogic
│ │ └── gdx
│ │ │ ├── backends
│ │ │ └── lwjgl3
│ │ │ │ └── DefaultLwjgl3Input.java
│ │ │ └── scenes
│ │ │ └── scene2d
│ │ │ ├── ui
│ │ │ ├── ScrollPane.java
│ │ │ └── TextField.java
│ │ │ └── utils
│ │ │ ├── DragAndDrop.java
│ │ │ └── DragListener.java
│ │ └── ray3k
│ │ ├── gdxparticleeditor
│ │ ├── Core.java
│ │ ├── FileDialogs.java
│ │ ├── Listeners.java
│ │ ├── ParticlePreview.java
│ │ ├── PresetActions.java
│ │ ├── PreviewSettings.java
│ │ ├── Settings.java
│ │ ├── SkinLoader.java
│ │ ├── SplitPaneSystemCursorListener.java
│ │ ├── SystemCursorListener.java
│ │ ├── TextFileApplicationLogger.java
│ │ ├── Utils.java
│ │ ├── lwjgl3
│ │ │ ├── Lwjgl3Launcher.java
│ │ │ └── StartupHelper.java
│ │ ├── runnables
│ │ │ ├── ExportRunnable.java
│ │ │ ├── ImagesRunnable.java
│ │ │ ├── MergeRunnable.java
│ │ │ ├── OpenRunnable.java
│ │ │ ├── RedoShortcutRunnable.java
│ │ │ ├── ReloadImagesRunnable.java
│ │ │ ├── SaveAsRunnable.java
│ │ │ ├── SaveRunnable.java
│ │ │ ├── SwitchModeRunnable.java
│ │ │ └── UndoShortcutRunnable.java
│ │ ├── shortcuts
│ │ │ ├── InvalidShortcutException.java
│ │ │ ├── KeyMap.java
│ │ │ ├── KeybindReference.java
│ │ │ ├── Shortcut.java
│ │ │ └── ShortcutManager.java
│ │ ├── undo
│ │ │ ├── UndoManager.java
│ │ │ ├── Undoable.java
│ │ │ └── undoables
│ │ │ │ ├── CountMaxUndoable.java
│ │ │ │ ├── CountMinUndoable.java
│ │ │ │ ├── DeleteEmitterUndoable.java
│ │ │ │ ├── DualScaledNumericValueRelativeUndoable.java
│ │ │ │ ├── DualScaledNumericValueUndoable.java
│ │ │ │ ├── ImagesAddUndoable.java
│ │ │ │ ├── ImagesMoveUndoable.java
│ │ │ │ ├── ImagesRemoveUndoable.java
│ │ │ │ ├── ImagesSpriteModeUndoable.java
│ │ │ │ ├── MergeEmitterUndoable.java
│ │ │ │ ├── MoveEmitterUndoable.java
│ │ │ │ ├── NewEmitterUndoable.java
│ │ │ │ ├── OptionsUndoable.java
│ │ │ │ ├── RangedNumericValueUndoable.java
│ │ │ │ ├── RenameEmitterUndoable.java
│ │ │ │ ├── ScaledNumericValueIndependentUndoable.java
│ │ │ │ ├── ScaledNumericValueRelativeUndoable.java
│ │ │ │ ├── ScaledNumericValueUndoable.java
│ │ │ │ ├── SetPropertyUndoable.java
│ │ │ │ ├── SpawnEdgesUndoable.java
│ │ │ │ ├── SpawnSideUndoable.java
│ │ │ │ ├── SpawnTypeUndoable.java
│ │ │ │ └── TintUndoable.java
│ │ └── widgets
│ │ │ ├── CardGroup.java
│ │ │ ├── Carousel.java
│ │ │ ├── CollapsibleGroup.java
│ │ │ ├── ColorGraph.java
│ │ │ ├── EditableLabel.java
│ │ │ ├── InfSlider.java
│ │ │ ├── LeadingTruncateLabel.java
│ │ │ ├── LineGraph.java
│ │ │ ├── NoCaptureKeyboardFocusListener.java
│ │ │ ├── Panel.java
│ │ │ ├── Toast.java
│ │ │ ├── ToggleGroup.java
│ │ │ ├── WelcomeCard.java
│ │ │ ├── panels
│ │ │ ├── EffectEmittersPanel.java
│ │ │ ├── EmitterPropertiesPanel.java
│ │ │ ├── PreviewPanel.java
│ │ │ ├── StartPanel.java
│ │ │ └── SummaryPanel.java
│ │ │ ├── poptables
│ │ │ ├── PopAddProperty.java
│ │ │ ├── PopConfirmClose.java
│ │ │ ├── PopConfirmLoad.java
│ │ │ ├── PopEditorSettings.java
│ │ │ ├── PopError.java
│ │ │ ├── PopExport.java
│ │ │ ├── PopImageError.java
│ │ │ ├── PopLocateImages.java
│ │ │ ├── PopPreviewSettings.java
│ │ │ └── PopTemplate.java
│ │ │ ├── styles
│ │ │ ├── PPcolorGraphStyle.java
│ │ │ ├── PPcolorPickerStyle.java
│ │ │ ├── PPdraggableListStyle.java
│ │ │ ├── PPdraggableTextListNoBGStyle.java
│ │ │ ├── PPdraggableTextListStyle.java
│ │ │ ├── PPeditableLabelStyle.java
│ │ │ ├── PPinfSliderStyle.java
│ │ │ ├── PPlineGraphBigStyle.java
│ │ │ ├── PPlineGraphStyle.java
│ │ │ ├── PPresizeWidgetStyle.java
│ │ │ ├── PPspinnerStyle.java
│ │ │ └── Styles.java
│ │ │ ├── subpanels
│ │ │ ├── CountSubPanel.java
│ │ │ ├── GraphSubPanel.java
│ │ │ ├── ImagesSubPanel.java
│ │ │ ├── OptionsSubPanel.java
│ │ │ ├── RangeSubPanel.java
│ │ │ ├── SizeSubPanel.java
│ │ │ ├── SpawnSubPanel.java
│ │ │ ├── TintSubPanel.java
│ │ │ └── TransparencySubPanel.java
│ │ │ └── tables
│ │ │ ├── ClassicTable.java
│ │ │ ├── WelcomeTable.java
│ │ │ └── WizardTable.java
│ │ └── stripe
│ │ ├── DraggableList.java
│ │ ├── DraggableTextList.java
│ │ ├── PopColorPicker.java
│ │ ├── PopTable.java
│ │ ├── PopTableHoverListener.java
│ │ ├── ResizeWidget.java
│ │ ├── ScrollFocusListener.java
│ │ ├── Spinner.java
│ │ └── ViewportWidget.java
│ └── resources
│ ├── icon128.png
│ ├── icon16.png
│ ├── icon32.png
│ ├── icon64.png
│ └── version
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.editorconfig:
--------------------------------------------------------------------------------
1 | # https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.{java,scala,groovy,kt,kts}]
12 | indent_size = 4
13 |
14 | [*.gradle]
15 | indent_size = 2
16 |
17 | [*.md]
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | *.bat text=auto eol=crlf
3 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Build GDX Particle Editor and create a draft release
2 |
3 | on:
4 | create
5 |
6 | jobs:
7 | jar:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 |
12 | - name: Set up JDK 14
13 | uses: actions/setup-java@v1
14 | with:
15 | java-version: 14
16 |
17 | - name: Fix gradlew file permissions
18 | run: chmod +x gradlew
19 |
20 | - name: Build jar
21 | run: ./gradlew core:jar
22 |
23 | - name: Upload jar artifact
24 | uses: actions/upload-artifact@v4
25 | with:
26 | name: gdx-particle-editor.jar
27 | path: core/build/lib/gdx-particle-editor.jar
28 |
29 | release:
30 | permissions: write-all
31 | needs: [jar]
32 | runs-on: ubuntu-latest
33 | steps:
34 | - name: Download all artifacts
35 | uses: actions/download-artifact@v4
36 |
37 | - name: Display structure of downloaded files
38 | run: ls -R
39 |
40 | - name: Create Release
41 | id: create_release
42 | uses: actions/create-release@v1
43 | env:
44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45 | with:
46 | tag_name: ${{ github.ref }}
47 | release_name: GDX Particle Editor ver. ${{ github.ref }}
48 | draft: true
49 | prerelease: false
50 |
51 | - name: Upload jar release artifacts
52 | uses: actions/upload-release-asset@v1
53 | env:
54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55 | with:
56 | upload_url: ${{ steps.create_release.outputs.upload_url }}
57 | asset_path: gdx-particle-editor.jar/gdx-particle-editor.jar
58 | asset_name: gdx-particle-editor.jar
59 | asset_content_type: application/x-java-archive
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## App:
2 | /design/
3 |
4 | ## Gradle:
5 | .gradle/
6 | gradle-app.setting
7 | /build/
8 | /android/build/
9 | /core/build/
10 | /lwjgl2/build/
11 | /lwjgl3/build/
12 | /html/build/
13 | /teavm/build/
14 | /ios/build/
15 | /ios-moe/build/
16 | /headless/build/
17 | /server/build/
18 | /shared/build/
19 |
20 | ## Java:
21 | *.class
22 | *.war
23 | *.ear
24 | hs_err_pid*
25 | .attach_pid*
26 |
27 | ## Android:
28 | /android/libs/armeabi-v7a/
29 | /android/libs/arm64-v8a/
30 | /android/libs/x86/
31 | /android/libs/x86_64/
32 | /android/gen/
33 | /android/out/
34 | local.properties
35 | com_crashlytics_export_strings.xml
36 |
37 | ## Robovm:
38 | /ios/robovm-build/
39 |
40 | ## iOS:
41 | /ios/xcode/*.xcodeproj/*
42 | !/ios/xcode/*.xcodeproj/xcshareddata
43 | !/ios/xcode/*.xcodeproj/project.pbxproj
44 | /ios/xcode/native/
45 | /ios/IOSLauncher.app
46 | /ios/IOSLauncher.app.dSYM
47 |
48 | ## GWT:
49 | /html/war/
50 | /html/gwt-unitCache/
51 | .apt_generated/
52 | /html/war/WEB-INF/deploy/
53 | /html/war/WEB-INF/classes/
54 | .gwt/
55 | gwt-unitCache/
56 | www-test/
57 | .gwt-tmp/
58 |
59 | ## TeaVM:
60 | # Not sure yet...
61 |
62 | ## IntelliJ, Android Studio:
63 | .idea/
64 | *.ipr
65 | *.iws
66 | *.iml
67 |
68 | ## Eclipse:
69 | .classpath
70 | .project
71 | .metadata/
72 | /android/bin/
73 | /core/bin/
74 | /lwjgl2/bin/
75 | /lwjgl3/bin/
76 | /html/bin/
77 | /teavm/bin/
78 | /ios/bin/
79 | /ios-moe/bin/
80 | /headless/bin/
81 | /server/bin/
82 | /shared/bin/
83 | *.tmp
84 | *.bak
85 | *.swp
86 | *~.nib
87 | .settings/
88 | .loadpath
89 | .externalToolBuilders/
90 | *.launch
91 |
92 |
93 | ## NetBeans:
94 |
95 | /nbproject/private/
96 | /android/nbproject/private/
97 | /core/nbproject/private/
98 | /lwjgl2/nbproject/private/
99 | /lwjgl3/nbproject/private/
100 | /html/nbproject/private/
101 | /teavm/nbproject/private/
102 | /ios/nbproject/private/
103 | /ios-moe/nbproject/private/
104 | /headless/nbproject/private/
105 | /server/nbproject/private/
106 | /shared/nbproject/private/
107 |
108 | /nbbuild/
109 | /android/nbbuild/
110 | /core/nbbuild/
111 | /lwjgl2/nbbuild/
112 | /lwjgl3/nbbuild/
113 | /html/nbbuild/
114 | /teavm/nbbuild/
115 | /ios/nbbuild/
116 | /ios-moe/nbbuild/
117 | /headless/nbbuild/
118 | /server/nbbuild/
119 | /shared/nbbuild/
120 |
121 | /dist/
122 | /android/dist/
123 | /core/dist/
124 | /lwjgl2/dist/
125 | /lwjgl3/dist/
126 | /html/dist/
127 | /teavm/dist/
128 | /ios/dist/
129 | /ios-moe/dist/
130 | /headless/dist/
131 | /server/dist/
132 | /shared/dist/
133 |
134 | /nbdist/
135 | /android/nbdist/
136 | /core/nbdist/
137 | /lwjgl2/nbdist/
138 | /lwjgl3/nbdist/
139 | /html/nbdist/
140 | /teavm/nbdist/
141 | /ios/nbdist/
142 | /ios-moe/nbdist/
143 | /headless/nbdist/
144 | /server/nbdist/
145 | /shared/nbdist/
146 |
147 | nbactions.xml
148 | nb-configuration.xml
149 |
150 | ## OS-Specific:
151 | .DS_Store
152 | Thumbs.db
153 |
154 | ## Miscellaneous:
155 | *~
156 | *.*#
157 | *#*#
158 |
--------------------------------------------------------------------------------
/KNOWN_ISSUES.md:
--------------------------------------------------------------------------------
1 | # Known Issues
2 | * YOUTUBE button does nothing. I haven't made the videos yet.
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GDX Particle Editor
2 | [](https://github.com/libgdx/gdx-particle-editor/blob/master/LICENSE)
3 | [](https://github.com/libgdx/gdx-particle-editor/releases)
4 |
5 | [
](https://github.com/libgdx/gdx-particle-editor/releases)
6 |
7 | ## Purpose
8 |
9 | The GDX Particle Editor is now the official particle editor for libGDX. These are the goals of the project:
10 |
11 | * Target all desktop platforms including M1 Macs.
12 | * Disallow any use of Swing, AWT, or similar toolkits. GDX Particle Editor is solely a Scene2D.UI project.
13 | * Improve the workflow and interface for maximum efficiency and attractiveness.
14 | * Export libGDX compatible particle effects. Extra features requiring a separate runtime library will not be supported.
15 | * Include all features available in the original [Particle Editor](https://github.com/libgdx/libgdx/tree/master/extensions/gdx-tools/src/com/badlogic/gdx/tools/particleeditor).
16 |
17 | ## How to run
18 |
19 | * Download the latest release from here: [releases](https://github.com/libgdx/gdx-particle-editor/releases)
20 | * Ensure you have at least JDK 11 installed on your system: [download](https://bell-sw.com/pages/downloads/)
21 | * Run the jar file: `java -jar gdx-particle-editor.jar`
22 |
23 | ## How to create particles
24 |
25 | Please read the [wiki](https://github.com/libgdx/gdx-particle-editor/wiki) to learn about creating particle effects and running GDX Particle Editor.
26 |
27 | ## How to contribute
28 |
29 | This project is maintained by Raymond "Raeleus" Buckley.
30 | * You may create an [issue](https://github.com/libgdx/gdx-particle-editor/issues) in GitHub if you encountered a crash or have a feature request. Please include a crash log. This is typically found in the user path ex. `C:\Users\\.gdxparticleeditor\`
31 | * See [CHANGES](https://github.com/libgdx/gdx-particle-editor/blob/master/CHANGES.md) and [KNOWN_ISSUES](https://github.com/libgdx/gdx-particle-editor/blob/master/KNOWN_ISSUES.md) for more details on development
32 | * Please target the `dev` branch for all PR's
33 |
--------------------------------------------------------------------------------
/assets/.gitkeep:
--------------------------------------------------------------------------------
1 | This file can be deleted if there are any other files present in this folder.
2 | It is only here to ensure this folder is added to Git, instead of being
3 | ignored because it is empty.
--------------------------------------------------------------------------------
/assets/blank.p:
--------------------------------------------------------------------------------
1 | Untitled
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 0.0
6 | lowMax: 0.0
7 | - Count -
8 | min: 0
9 | max: 0
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 0.0
14 | highMax: 0.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 0.0
24 | highMax: 0.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: point
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 0.0
44 | highMax: 0.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 0.0
64 | highMax: 0.0
65 | relative: false
66 | scalingCount: 1
67 | scaling0: 1.0
68 | timelineCount: 1
69 | timeline0: 0.0
70 | - Y Scale -
71 | active: false
72 | - Velocity -
73 | active: false
74 | - Angle -
75 | active: false
76 | - Rotation -
77 | active: false
78 | - Wind -
79 | active: false
80 | - Gravity -
81 | active: false
82 | - Tint -
83 | colorsCount: 3
84 | colors0: 1.0
85 | colors1: 1.0
86 | colors2: 1.0
87 | timelineCount: 1
88 | timeline0: 0.0
89 | - Transparency -
90 | lowMin: 0.0
91 | lowMax: 0.0
92 | highMin: 1.0
93 | highMax: 1.0
94 | relative: false
95 | scalingCount: 1
96 | scaling0: 1.0
97 | timelineCount: 1
98 | timeline0: 0.0
99 | - Options -
100 | attached: false
101 | continuous: true
102 | aligned: false
103 | additive: false
104 | behind: false
105 | premultipliedAlpha: false
106 | spriteMode: single
107 | - Image Paths -
108 | particle.png
109 |
110 |
--------------------------------------------------------------------------------
/assets/default/default.atlas:
--------------------------------------------------------------------------------
1 | default.png
2 | size:512,512
3 | filter:Linear,Linear
4 | logo
5 | bounds:1,457,300,50
6 | particle
7 | bounds:303,475,32,32
8 | particle-ball1
9 | bounds:1,327,128,128
10 | particle-ball2
11 | bounds:1,197,128,128
12 | particle-ball3
13 | bounds:131,327,128,128
14 | particle-ball4
15 | bounds:1,67,128,128
16 | particle-cloud
17 | bounds:131,197,128,128
18 | particle-fire
19 | bounds:131,67,128,128
20 | particle-star
21 | bounds:1,1,64,64
22 | pre_particle
23 | bounds:261,423,32,32
24 |
--------------------------------------------------------------------------------
/assets/default/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/default/default.png
--------------------------------------------------------------------------------
/assets/demolition.p:
--------------------------------------------------------------------------------
1 | Demolition
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 1000.0
6 | lowMax: 1000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 50.0
14 | highMax: 50.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 200.0
24 | highMax: 200.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: ellipse
40 | edges: false
41 | side: both
42 | - Spawn Width -
43 | lowMin: 0.0
44 | lowMax: 0.0
45 | highMin: 100.0
46 | highMax: 100.0
47 | relative: false
48 | scalingCount: 1
49 | scaling0: 1.0
50 | timelineCount: 1
51 | timeline0: 0.0
52 | - Spawn Height -
53 | lowMin: 0.0
54 | lowMax: 0.0
55 | highMin: 100.0
56 | highMax: 100.0
57 | relative: false
58 | scalingCount: 1
59 | scaling0: 1.0
60 | timelineCount: 1
61 | timeline0: 0.0
62 | - X Scale -
63 | lowMin: 0.0
64 | lowMax: 0.0
65 | highMin: 30.0
66 | highMax: 60.0
67 | relative: false
68 | scalingCount: 1
69 | scaling0: 1.0
70 | timelineCount: 1
71 | timeline0: 0.0
72 | - Y Scale -
73 | active: false
74 | - Velocity -
75 | active: true
76 | lowMin: 0.0
77 | lowMax: 0.0
78 | highMin: 0.0
79 | highMax: 0.0
80 | relative: false
81 | scalingCount: 1
82 | scaling0: 1.0
83 | timelineCount: 1
84 | timeline0: 0.0
85 | - Angle -
86 | active: true
87 | lowMin: 0.0
88 | lowMax: 0.0
89 | highMin: 0.0
90 | highMax: 360.0
91 | relative: false
92 | scalingCount: 1
93 | scaling0: 1.0
94 | timelineCount: 1
95 | timeline0: 0.0
96 | - Rotation -
97 | active: true
98 | lowMin: 0.0
99 | lowMax: 0.0
100 | highMin: 0.0
101 | highMax: 360.0
102 | relative: false
103 | scalingCount: 1
104 | scaling0: 1.0
105 | timelineCount: 1
106 | timeline0: 0.0
107 | - Wind -
108 | active: false
109 | - Gravity -
110 | active: false
111 | - Tint -
112 | colorsCount: 9
113 | colors0: 1.0
114 | colors1: 1.0
115 | colors2: 1.0
116 | colors3: 0.91764706
117 | colors4: 1.0
118 | colors5: 0.0
119 | colors6: 1.0
120 | colors7: 0.0
121 | colors8: 0.0
122 | timelineCount: 3
123 | timeline0: 0.0
124 | timeline1: 0.10000006
125 | timeline2: 1.0
126 | - Transparency -
127 | lowMin: 0.0
128 | lowMax: 0.0
129 | highMin: 1.0
130 | highMax: 1.0
131 | relative: false
132 | scalingCount: 1
133 | scaling0: 1.0
134 | timelineCount: 1
135 | timeline0: 0.0
136 | - Options -
137 | attached: false
138 | continuous: true
139 | aligned: false
140 | additive: false
141 | behind: false
142 | premultipliedAlpha: false
143 | spriteMode: animated
144 | - Image Paths -
145 | particle-ball1.png
146 | particle-ball2.png
147 | particle-ball3.png
148 | particle-ball4.png
149 |
150 |
--------------------------------------------------------------------------------
/assets/flame.p:
--------------------------------------------------------------------------------
1 | Flame
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 3000.0
6 | lowMax: 3000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 250.0
14 | highMax: 250.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 500.0
24 | highMax: 1000.0
25 | relative: false
26 | scalingCount: 3
27 | scaling0: 1.0
28 | scaling1: 1.0
29 | scaling2: 0.3
30 | timelineCount: 3
31 | timeline0: 0.0
32 | timeline1: 0.66
33 | timeline2: 1.0
34 | independent: false
35 | - Life Offset -
36 | active: false
37 | independent: false
38 | - X Offset -
39 | active: false
40 | - Y Offset -
41 | active: false
42 | - Spawn Shape -
43 | shape: point
44 | - Spawn Width -
45 | lowMin: 0.0
46 | lowMax: 0.0
47 | highMin: 0.0
48 | highMax: 0.0
49 | relative: false
50 | scalingCount: 1
51 | scaling0: 1.0
52 | timelineCount: 1
53 | timeline0: 0.0
54 | - Spawn Height -
55 | lowMin: 0.0
56 | lowMax: 0.0
57 | highMin: 0.0
58 | highMax: 0.0
59 | relative: false
60 | scalingCount: 1
61 | scaling0: 1.0
62 | timelineCount: 1
63 | timeline0: 0.0
64 | - X Scale -
65 | lowMin: 0.0
66 | lowMax: 0.0
67 | highMin: 32.0
68 | highMax: 32.0
69 | relative: false
70 | scalingCount: 1
71 | scaling0: 1.0
72 | timelineCount: 1
73 | timeline0: 0.0
74 | - Y Scale -
75 | active: false
76 | - Velocity -
77 | active: true
78 | lowMin: 0.0
79 | lowMax: 0.0
80 | highMin: 30.0
81 | highMax: 300.0
82 | relative: false
83 | scalingCount: 1
84 | scaling0: 1.0
85 | timelineCount: 1
86 | timeline0: 0.0
87 | - Angle -
88 | active: true
89 | lowMin: 90.0
90 | lowMax: 90.0
91 | highMin: 45.0
92 | highMax: 135.0
93 | relative: false
94 | scalingCount: 3
95 | scaling0: 1.0
96 | scaling1: 0.0
97 | scaling2: 0.0
98 | timelineCount: 3
99 | timeline0: 0.0
100 | timeline1: 0.5
101 | timeline2: 1.0
102 | - Rotation -
103 | active: false
104 | - Wind -
105 | active: false
106 | - Gravity -
107 | active: false
108 | - Tint -
109 | colorsCount: 3
110 | colors0: 1.0
111 | colors1: 0.12156863
112 | colors2: 0.047058824
113 | timelineCount: 1
114 | timeline0: 0.0
115 | - Transparency -
116 | lowMin: 0.0
117 | lowMax: 0.0
118 | highMin: 1.0
119 | highMax: 1.0
120 | relative: false
121 | scalingCount: 4
122 | scaling0: 0.0
123 | scaling1: 1.0
124 | scaling2: 0.75
125 | scaling3: 0.0
126 | timelineCount: 4
127 | timeline0: 0.0
128 | timeline1: 0.2
129 | timeline2: 0.8
130 | timeline3: 1.0
131 | - Options -
132 | attached: false
133 | continuous: true
134 | aligned: false
135 | additive: true
136 | behind: false
137 | premultipliedAlpha: false
138 | spriteMode: single
139 | - Image Paths -
140 | particle.png
141 |
142 |
--------------------------------------------------------------------------------
/assets/glitch.p:
--------------------------------------------------------------------------------
1 | Glitch
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 10000.0
6 | lowMax: 10000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 14.0
14 | highMax: 14.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 500.0
24 | highMax: 500.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: true
36 | lowMin: -3.0
37 | lowMax: 3.0
38 | highMin: 0.0
39 | highMax: 0.0
40 | relative: false
41 | scalingCount: 1
42 | scaling0: 1.0
43 | timelineCount: 1
44 | timeline0: 0.0
45 | - Y Offset -
46 | active: true
47 | lowMin: -3.0
48 | lowMax: 3.0
49 | highMin: 0.0
50 | highMax: 0.0
51 | relative: false
52 | scalingCount: 1
53 | scaling0: 1.0
54 | timelineCount: 1
55 | timeline0: 0.0
56 | - Spawn Shape -
57 | shape: point
58 | - Spawn Width -
59 | lowMin: 0.0
60 | lowMax: 0.0
61 | highMin: 0.0
62 | highMax: 0.0
63 | relative: false
64 | scalingCount: 1
65 | scaling0: 1.0
66 | timelineCount: 1
67 | timeline0: 0.0
68 | - Spawn Height -
69 | lowMin: 0.0
70 | lowMax: 0.0
71 | highMin: 0.0
72 | highMax: 0.0
73 | relative: false
74 | scalingCount: 1
75 | scaling0: 1.0
76 | timelineCount: 1
77 | timeline0: 0.0
78 | - X Scale -
79 | lowMin: 0.0
80 | lowMax: 0.0
81 | highMin: 200.0
82 | highMax: 200.0
83 | relative: false
84 | scalingCount: 1
85 | scaling0: 1.0
86 | timelineCount: 1
87 | timeline0: 0.0
88 | - Y Scale -
89 | active: false
90 | - Velocity -
91 | active: false
92 | - Angle -
93 | active: false
94 | - Rotation -
95 | active: false
96 | - Wind -
97 | active: false
98 | - Gravity -
99 | active: false
100 | - Tint -
101 | colorsCount: 27
102 | colors0: 1.0
103 | colors1: 0.047058824
104 | colors2: 0.047058824
105 | colors3: 1.0
106 | colors4: 0.69411767
107 | colors5: 0.047058824
108 | colors6: 0.95686275
109 | colors7: 1.0
110 | colors8: 0.047058824
111 | colors9: 0.047058824
112 | colors10: 1.0
113 | colors11: 0.09019608
114 | colors12: 0.047058824
115 | colors13: 0.9254902
116 | colors14: 1.0
117 | colors15: 0.047058824
118 | colors16: 0.11764706
119 | colors17: 1.0
120 | colors18: 0.4509804
121 | colors19: 0.047058824
122 | colors20: 1.0
123 | colors21: 1.0
124 | colors22: 0.047058824
125 | colors23: 0.972549
126 | colors24: 1.0
127 | colors25: 0.047058824
128 | colors26: 0.047058824
129 | timelineCount: 9
130 | timeline0: 0.0
131 | timeline1: 0.16351119
132 | timeline2: 0.2616179
133 | timeline3: 0.38554215
134 | timeline4: 0.51979345
135 | timeline5: 0.6506024
136 | timeline6: 0.7555938
137 | timeline7: 0.8915663
138 | timeline8: 1.0
139 | - Transparency -
140 | lowMin: 0.0
141 | lowMax: 0.0
142 | highMin: 1.0
143 | highMax: 1.0
144 | relative: false
145 | scalingCount: 1
146 | scaling0: 1.0
147 | timelineCount: 1
148 | timeline0: 0.0
149 | - Options -
150 | attached: true
151 | continuous: true
152 | aligned: false
153 | additive: true
154 | behind: false
155 | premultipliedAlpha: false
156 | spriteMode: single
157 | - Image Paths -
158 | logo.png
159 |
160 |
--------------------------------------------------------------------------------
/assets/laser.p:
--------------------------------------------------------------------------------
1 | Laser
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 1000.0
6 | lowMax: 1000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 200.0
14 | highMax: 200.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 600.0
24 | highMax: 600.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: line
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 500.0
44 | highMax: 500.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 2.0
64 | highMax: 2.0
65 | relative: false
66 | scalingCount: 1
67 | scaling0: 1.0
68 | timelineCount: 1
69 | timeline0: 0.0
70 | - Y Scale -
71 | active: false
72 | - Velocity -
73 | active: true
74 | lowMin: 0.0
75 | lowMax: 90.0
76 | highMin: 0.0
77 | highMax: 90.0
78 | relative: false
79 | scalingCount: 2
80 | scaling0: 0.0
81 | scaling1: 1.0
82 | timelineCount: 2
83 | timeline0: 0.0
84 | timeline1: 1.0
85 | - Angle -
86 | active: true
87 | lowMin: 0.0
88 | lowMax: 0.0
89 | highMin: 0.0
90 | highMax: 0.0
91 | relative: false
92 | scalingCount: 1
93 | scaling0: 1.0
94 | timelineCount: 1
95 | timeline0: 0.0
96 | - Rotation -
97 | active: false
98 | - Wind -
99 | active: false
100 | - Gravity -
101 | active: false
102 | - Tint -
103 | colorsCount: 3
104 | colors0: 1.0
105 | colors1: 0.047058824
106 | colors2: 0.047058824
107 | timelineCount: 1
108 | timeline0: 0.0
109 | - Transparency -
110 | lowMin: 0.0
111 | lowMax: 0.0
112 | highMin: 1.0
113 | highMax: 1.0
114 | relative: false
115 | scalingCount: 3
116 | scaling0: 0.0
117 | scaling1: 1.0
118 | scaling2: 0.0
119 | timelineCount: 3
120 | timeline0: 0.0
121 | timeline1: 0.63013697
122 | timeline2: 1.0
123 | - Options -
124 | attached: true
125 | continuous: true
126 | aligned: true
127 | additive: false
128 | behind: false
129 | premultipliedAlpha: false
130 | spriteMode: single
131 | - Image Paths -
132 | particle.png
133 |
134 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/logo.png
--------------------------------------------------------------------------------
/assets/particle-ball1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-ball1.png
--------------------------------------------------------------------------------
/assets/particle-ball2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-ball2.png
--------------------------------------------------------------------------------
/assets/particle-ball3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-ball3.png
--------------------------------------------------------------------------------
/assets/particle-ball4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-ball4.png
--------------------------------------------------------------------------------
/assets/particle-cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-cloud.png
--------------------------------------------------------------------------------
/assets/particle-fire.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-fire.png
--------------------------------------------------------------------------------
/assets/particle-star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle-star.png
--------------------------------------------------------------------------------
/assets/particle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/particle.png
--------------------------------------------------------------------------------
/assets/pre_particle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/pre_particle.png
--------------------------------------------------------------------------------
/assets/rain.p:
--------------------------------------------------------------------------------
1 | Rain
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 1000.0
6 | lowMax: 1000.0
7 | - Count -
8 | min: 0
9 | max: 2000
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 20.0
14 | highMax: 20.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 10000.0
24 | highMax: 10000.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: line
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 800.0
44 | highMax: 800.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 2.0
64 | highMax: 2.0
65 | relative: false
66 | scalingCount: 1
67 | scaling0: 1.0
68 | timelineCount: 1
69 | timeline0: 0.0
70 | - Y Scale -
71 | active: true
72 | lowMin: 0.0
73 | lowMax: 0.0
74 | highMin: 200.0
75 | highMax: 200.0
76 | relative: false
77 | scalingCount: 2
78 | scaling0: 0.0
79 | scaling1: 1.0
80 | timelineCount: 2
81 | timeline0: 0.0
82 | timeline1: 0.041666668
83 | - Velocity -
84 | active: true
85 | lowMin: 0.0
86 | lowMax: 0.0
87 | highMin: 520.0
88 | highMax: 600.0
89 | relative: false
90 | scalingCount: 1
91 | scaling0: 1.0
92 | timelineCount: 1
93 | timeline0: 0.0
94 | - Angle -
95 | active: true
96 | lowMin: 0.0
97 | lowMax: 0.0
98 | highMin: 240.0
99 | highMax: 240.0
100 | relative: false
101 | scalingCount: 1
102 | scaling0: 1.0
103 | timelineCount: 1
104 | timeline0: 0.0
105 | - Rotation -
106 | active: true
107 | lowMin: 0.0
108 | lowMax: 0.0
109 | highMin: 150.0
110 | highMax: 150.0
111 | relative: false
112 | scalingCount: 1
113 | scaling0: 1.0
114 | timelineCount: 1
115 | timeline0: 0.0
116 | - Wind -
117 | active: false
118 | - Gravity -
119 | active: false
120 | - Tint -
121 | colorsCount: 3
122 | colors0: 1.0
123 | colors1: 1.0
124 | colors2: 1.0
125 | timelineCount: 1
126 | timeline0: 0.0
127 | - Transparency -
128 | lowMin: 0.0
129 | lowMax: 0.0
130 | highMin: 1.0
131 | highMax: 1.0
132 | relative: false
133 | scalingCount: 4
134 | scaling0: 0.0
135 | scaling1: 1.0
136 | scaling2: 1.0
137 | scaling3: 0.0
138 | timelineCount: 4
139 | timeline0: 0.0
140 | timeline1: 0.11111132
141 | timeline2: 0.9027782
142 | timeline3: 1.0
143 | - Options -
144 | attached: false
145 | continuous: true
146 | aligned: false
147 | additive: false
148 | behind: false
149 | premultipliedAlpha: false
150 | spriteMode: single
151 | - Image Paths -
152 | particle.png
153 |
154 |
--------------------------------------------------------------------------------
/assets/skin/gdxparticleeditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/assets/skin/gdxparticleeditor.png
--------------------------------------------------------------------------------
/assets/smoke.p:
--------------------------------------------------------------------------------
1 | Smoke
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 3000.0
6 | lowMax: 3000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 5.0
14 | highMax: 5.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 6000.0
24 | highMax: 6000.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: point
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 0.0
44 | highMax: 0.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 40.0
62 | lowMax: 40.0
63 | highMin: 80.0
64 | highMax: 80.0
65 | relative: true
66 | scalingCount: 2
67 | scaling0: 0.0
68 | scaling1: 1.0
69 | timelineCount: 2
70 | timeline0: 0.0
71 | timeline1: 1.0
72 | - Y Scale -
73 | active: false
74 | - Velocity -
75 | active: true
76 | lowMin: 0.0
77 | lowMax: 0.0
78 | highMin: 50.0
79 | highMax: 50.0
80 | relative: false
81 | scalingCount: 1
82 | scaling0: 1.0
83 | timelineCount: 1
84 | timeline0: 0.0
85 | - Angle -
86 | active: true
87 | lowMin: 0.0
88 | lowMax: 0.0
89 | highMin: 75.0
90 | highMax: 105.0
91 | relative: false
92 | scalingCount: 1
93 | scaling0: 1.0
94 | timelineCount: 1
95 | timeline0: 0.0
96 | - Rotation -
97 | active: true
98 | lowMin: 0.0
99 | lowMax: 360.0
100 | highMin: -100.0
101 | highMax: 100.0
102 | relative: true
103 | scalingCount: 2
104 | scaling0: 0.0
105 | scaling1: 1.0
106 | timelineCount: 2
107 | timeline0: 0.0
108 | timeline1: 1.0
109 | - Wind -
110 | active: false
111 | - Gravity -
112 | active: false
113 | - Tint -
114 | colorsCount: 3
115 | colors0: 0.5764706
116 | colors1: 0.5764706
117 | colors2: 0.5764706
118 | timelineCount: 1
119 | timeline0: 0.0
120 | - Transparency -
121 | lowMin: 0.0
122 | lowMax: 0.0
123 | highMin: 1.0
124 | highMax: 1.0
125 | relative: false
126 | scalingCount: 4
127 | scaling0: 0.0
128 | scaling1: 1.0
129 | scaling2: 1.0
130 | scaling3: 0.0
131 | timelineCount: 4
132 | timeline0: 0.0
133 | timeline1: 0.21527798
134 | timeline2: 0.805556
135 | timeline3: 1.0
136 | - Options -
137 | attached: false
138 | continuous: true
139 | aligned: false
140 | additive: false
141 | behind: false
142 | premultipliedAlpha: false
143 | spriteMode: single
144 | - Image Paths -
145 | particle-cloud.png
146 |
147 |
--------------------------------------------------------------------------------
/assets/sparks.p:
--------------------------------------------------------------------------------
1 | Sparks
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 3000.0
6 | lowMax: 3000.0
7 | - Count -
8 | min: 0
9 | max: 200
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 90.0
14 | highMax: 90.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 500.0
24 | highMax: 1000.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: point
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 0.0
44 | highMax: 0.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 5.0
64 | highMax: 19.0
65 | relative: false
66 | scalingCount: 3
67 | scaling0: 0.0
68 | scaling1: 1.0
69 | scaling2: 0.0
70 | timelineCount: 3
71 | timeline0: 0.0
72 | timeline1: 0.30555555
73 | timeline2: 1.0
74 | - Y Scale -
75 | active: false
76 | - Velocity -
77 | active: true
78 | lowMin: 0.0
79 | lowMax: 0.0
80 | highMin: 30.0
81 | highMax: 285.0
82 | relative: false
83 | scalingCount: 1
84 | scaling0: 1.0
85 | timelineCount: 1
86 | timeline0: 0.0
87 | - Angle -
88 | active: true
89 | lowMin: 0.0
90 | lowMax: 0.0
91 | highMin: 0.0
92 | highMax: 360.0
93 | relative: false
94 | scalingCount: 1
95 | scaling0: 1.0
96 | timelineCount: 1
97 | timeline0: 0.0
98 | - Rotation -
99 | active: true
100 | lowMin: 0.0
101 | lowMax: 360.0
102 | highMin: -360.0
103 | highMax: 360.0
104 | relative: true
105 | scalingCount: 2
106 | scaling0: 0.0
107 | scaling1: 1.0
108 | timelineCount: 2
109 | timeline0: 0.0
110 | timeline1: 1.0
111 | - Wind -
112 | active: false
113 | - Gravity -
114 | active: true
115 | lowMin: 0.0
116 | lowMax: 0.0
117 | highMin: -405.0
118 | highMax: -405.0
119 | relative: true
120 | scalingCount: 2
121 | scaling0: 0.0
122 | scaling1: 1.0
123 | timelineCount: 2
124 | timeline0: 0.0
125 | timeline1: 1.0
126 | - Tint -
127 | colorsCount: 3
128 | colors0: 0.93333334
129 | colors1: 1.0
130 | colors2: 0.3764706
131 | timelineCount: 1
132 | timeline0: 0.0
133 | - Transparency -
134 | lowMin: 0.0
135 | lowMax: 0.0
136 | highMin: 1.0
137 | highMax: 1.0
138 | relative: false
139 | scalingCount: 4
140 | scaling0: 0.0
141 | scaling1: 1.0
142 | scaling2: 0.75
143 | scaling3: 0.0
144 | timelineCount: 4
145 | timeline0: 0.0
146 | timeline1: 0.2
147 | timeline2: 0.8
148 | timeline3: 1.0
149 | - Options -
150 | attached: false
151 | continuous: true
152 | aligned: false
153 | additive: false
154 | behind: false
155 | premultipliedAlpha: false
156 | spriteMode: single
157 | - Image Paths -
158 | particle-star.png
159 |
160 |
--------------------------------------------------------------------------------
/assets/thruster.p:
--------------------------------------------------------------------------------
1 | Thruster
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 200.0
6 | lowMax: 200.0
7 | - Count -
8 | min: 0
9 | max: 2000
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 75.0
14 | highMax: 75.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 500.0
24 | highMax: 500.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: point
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 0.0
44 | highMax: 0.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 30.0
64 | highMax: 30.0
65 | relative: false
66 | scalingCount: 2
67 | scaling0: 1.0
68 | scaling1: 0.0
69 | timelineCount: 2
70 | timeline0: 0.0
71 | timeline1: 1.0
72 | - Y Scale -
73 | active: false
74 | - Velocity -
75 | active: true
76 | lowMin: 0.0
77 | lowMax: 0.0
78 | highMin: 110.0
79 | highMax: 110.0
80 | relative: false
81 | scalingCount: 1
82 | scaling0: 1.0
83 | timelineCount: 1
84 | timeline0: 0.0
85 | - Angle -
86 | active: true
87 | lowMin: 0.0
88 | lowMax: 0.0
89 | highMin: 265.0
90 | highMax: 275.0
91 | relative: false
92 | scalingCount: 1
93 | scaling0: 1.0
94 | timelineCount: 1
95 | timeline0: 0.0
96 | - Rotation -
97 | active: true
98 | lowMin: 0.0
99 | lowMax: 0.0
100 | highMin: 0.0
101 | highMax: 360.0
102 | relative: false
103 | scalingCount: 1
104 | scaling0: 1.0
105 | timelineCount: 1
106 | timeline0: 0.0
107 | - Wind -
108 | active: false
109 | - Gravity -
110 | active: false
111 | - Tint -
112 | colorsCount: 12
113 | colors0: 1.0
114 | colors1: 1.0
115 | colors2: 1.0
116 | colors3: 0.96862745
117 | colors4: 0.9137255
118 | colors5: 0.0
119 | colors6: 0.96862745
120 | colors7: 0.4627451
121 | colors8: 0.0
122 | colors9: 0.96862745
123 | colors10: 0.0
124 | colors11: 0.0
125 | timelineCount: 4
126 | timeline0: 0.0
127 | timeline1: 0.13018873
128 | timeline2: 0.34528303
129 | timeline3: 1.0
130 | - Transparency -
131 | lowMin: 0.0
132 | lowMax: 0.0
133 | highMin: 1.0
134 | highMax: 1.0
135 | relative: false
136 | scalingCount: 4
137 | scaling0: 0.0
138 | scaling1: 1.0
139 | scaling2: 1.0
140 | scaling3: 0.0
141 | timelineCount: 4
142 | timeline0: 0.0
143 | timeline1: 0.11111132
144 | timeline2: 0.7986111
145 | timeline3: 1.0
146 | - Options -
147 | attached: true
148 | continuous: true
149 | aligned: false
150 | additive: true
151 | behind: false
152 | premultipliedAlpha: false
153 | spriteMode: single
154 | - Image Paths -
155 | particle-fire.png
156 |
157 |
--------------------------------------------------------------------------------
/assets/trail.p:
--------------------------------------------------------------------------------
1 | Trail
2 | - Delay -
3 | active: false
4 | - Duration -
5 | lowMin: 200.0
6 | lowMax: 200.0
7 | - Count -
8 | min: 0
9 | max: 2000
10 | - Emission -
11 | lowMin: 0.0
12 | lowMax: 0.0
13 | highMin: 20.0
14 | highMax: 20.0
15 | relative: false
16 | scalingCount: 1
17 | scaling0: 1.0
18 | timelineCount: 1
19 | timeline0: 0.0
20 | - Life -
21 | lowMin: 0.0
22 | lowMax: 0.0
23 | highMin: 500.0
24 | highMax: 500.0
25 | relative: false
26 | scalingCount: 1
27 | scaling0: 1.0
28 | timelineCount: 1
29 | timeline0: 0.0
30 | independent: false
31 | - Life Offset -
32 | active: false
33 | independent: false
34 | - X Offset -
35 | active: false
36 | - Y Offset -
37 | active: false
38 | - Spawn Shape -
39 | shape: point
40 | - Spawn Width -
41 | lowMin: 0.0
42 | lowMax: 0.0
43 | highMin: 0.0
44 | highMax: 0.0
45 | relative: false
46 | scalingCount: 1
47 | scaling0: 1.0
48 | timelineCount: 1
49 | timeline0: 0.0
50 | - Spawn Height -
51 | lowMin: 0.0
52 | lowMax: 0.0
53 | highMin: 0.0
54 | highMax: 0.0
55 | relative: false
56 | scalingCount: 1
57 | scaling0: 1.0
58 | timelineCount: 1
59 | timeline0: 0.0
60 | - X Scale -
61 | lowMin: 0.0
62 | lowMax: 0.0
63 | highMin: 5.0
64 | highMax: 5.0
65 | relative: false
66 | scalingCount: 2
67 | scaling0: 1.0
68 | scaling1: 0.0
69 | timelineCount: 2
70 | timeline0: 0.0
71 | timeline1: 1.0
72 | - Y Scale -
73 | active: false
74 | - Velocity -
75 | active: false
76 | - Angle -
77 | active: false
78 | - Rotation -
79 | active: false
80 | - Wind -
81 | active: false
82 | - Gravity -
83 | active: false
84 | - Tint -
85 | colorsCount: 3
86 | colors0: 1.0
87 | colors1: 1.0
88 | colors2: 1.0
89 | timelineCount: 1
90 | timeline0: 0.0
91 | - Transparency -
92 | lowMin: 0.0
93 | lowMax: 0.0
94 | highMin: 1.0
95 | highMax: 1.0
96 | relative: false
97 | scalingCount: 1
98 | scaling0: 1.0
99 | timelineCount: 1
100 | timeline0: 0.0
101 | - Options -
102 | attached: false
103 | continuous: true
104 | aligned: false
105 | additive: false
106 | behind: false
107 | premultipliedAlpha: false
108 | spriteMode: single
109 | - Image Paths -
110 | particle.png
111 |
112 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | maven { url 'https://s01.oss.sonatype.org' }
5 | mavenLocal()
6 | google()
7 | gradlePluginPortal()
8 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
9 | maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
10 | }
11 | dependencies {
12 | classpath "io.freefair.gradle:lombok-plugin:6.5.0.3"
13 |
14 | }
15 | }
16 |
17 | allprojects {
18 | apply plugin: 'eclipse'
19 | apply plugin: 'idea'
20 | }
21 |
22 | configure(subprojects) {
23 | apply plugin: 'java-library'
24 | apply plugin: 'io.freefair.lombok'
25 | sourceCompatibility = 11
26 | compileJava {
27 | options.incremental = true
28 | }
29 | }
30 |
31 | task versionText {
32 | doLast {
33 | new File(projectDir, "core/src/main/resources/version").text = project(':core').version
34 | }
35 | }
36 |
37 | subprojects {
38 | version = '1.0.9'
39 | ext.appName = 'gdx-particle-editor'
40 | repositories {
41 | mavenCentral()
42 | maven { url 'https://s01.oss.sonatype.org' }
43 | // You may want to remove the following line if you have errors downloading dependencies.
44 | mavenLocal()
45 | gradlePluginPortal()
46 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
47 | maven { url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' }
48 | maven { url 'https://jitpack.io' }
49 | }
50 | }
51 |
52 | eclipse.project.name = 'gdx-particle-editor' + '-parent'
53 |
--------------------------------------------------------------------------------
/core/build.gradle:
--------------------------------------------------------------------------------
1 | [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
2 | eclipse.project.name = appName + '-core'
3 |
4 | buildscript {
5 | repositories {
6 | gradlePluginPortal()
7 | }
8 | dependencies {
9 | // using jpackage only works if the JDK version is 14 or higher.
10 | // your JAVA_HOME environment variable may also need to be a JDK with version 14 or higher.
11 | if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_14)) {
12 | classpath "org.beryx:badass-runtime-plugin:1.13.0"
13 | }
14 | }
15 | }
16 |
17 | if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_14)) {
18 | apply plugin: 'org.beryx.runtime'
19 | }
20 | else {
21 | apply plugin: 'application'
22 | }
23 |
24 | sourceSets.main.resources.srcDirs += [ rootProject.file('assets').path ]
25 | mainClassName = 'com.ray3k.gdxparticleeditor.lwjgl3.Lwjgl3Launcher'
26 | sourceCompatibility = 11
27 |
28 | dependencies {
29 | api "com.badlogicgames.gdx:gdx:$gdxVersion"
30 | implementation "com.badlogicgames.gdx:gdx-backend-lwjgl3:$gdxVersion"
31 | implementation "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
32 | api "org.projectlombok:lombok:$lombokVersion"
33 | annotationProcessor "org.projectlombok:lombok:$lombokVersion"
34 | api 'com.github.raeleus.TenPatch:tenpatch:5.2.3'
35 | implementation 'com.github.raeleus.stripe:stripe:1.4.5'
36 | implementation 'com.github.raeleus.stripe:colorpicker:1.4.5'
37 | implementation 'space.earlygrey:shapedrawer:2.5.0'
38 | implementation 'com.github.tommyettinger:colorful:0.8.4'
39 | implementation "org.lwjgl:lwjgl-tinyfd:3.3.2"
40 | implementation "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-windows"
41 | implementation "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-linux"
42 | implementation "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-macos"
43 | implementation "org.lwjgl:lwjgl-tinyfd:3.3.2:natives-macos-arm64"
44 | }
45 |
46 | def os = System.properties['os.name'].toLowerCase()
47 |
48 | run {
49 | workingDir = rootProject.file('assets').path
50 | setIgnoreExitValue(true)
51 |
52 | if (os.contains('mac')) {
53 | // Required to run LWJGL3 Java apps on macOS
54 | jvmArgs += "-XstartOnFirstThread"
55 | }
56 | }
57 |
58 | jar {
59 | // sets the name of the .jar file this produces to the name of the game or app.
60 | archiveFileName.set(appName + ".jar")
61 | // using 'lib' instead of the default 'libs' appears to be needed by jpackageimage.
62 | destinationDirectory = file("$project.buildDir/lib")
63 | // the duplicatesStrategy matters starting in Gradle 7.0; this setting works.
64 | duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
65 | dependsOn configurations.runtimeClasspath
66 | from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
67 | // these "exclude" lines remove some unnecessary duplicate files in the output JAR.
68 | exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
69 | dependencies {
70 | exclude('META-INF/INDEX.LIST', 'META-INF/maven/**')
71 | }
72 | // setting the manifest makes the JAR runnable.
73 | manifest {
74 | attributes 'Main-Class': project.mainClassName
75 | }
76 | // this last step may help on some OSes that need extra instruction to make runnable JARs.
77 | doLast {
78 | file(archiveFile).setExecutable(true, false)
79 | }
80 | }
81 |
82 | if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_14)) {
83 | tasks.jpackageImage.doNotTrackState("This task both reads from and writes to the build folder.")
84 | runtime {
85 | options.set(['--strip-debug',
86 | '--compress', '2',
87 | '--no-header-files',
88 | '--no-man-pages',
89 | '--strip-native-commands',
90 | '--vm', 'server'])
91 | // you could very easily need more modules than this one.
92 | // use the lwjgl3:suggestModules task to see which modules may be needed.
93 | modules.set([
94 | 'jdk.unsupported'
95 | ])
96 | distDir.set(file(buildDir))
97 | jpackage {
98 | imageName = appName
99 | // you can set this to false if you want to build an installer, or keep it as true to build just an app.
100 | skipInstaller = true
101 | // this may need to be set to a different path if your JAVA_HOME points to a low JDK version.
102 | jpackageHome = javaHome.getOrElse("")
103 | mainJar = jar.archiveFileName.get()
104 | if (os.contains('win')) {
105 | imageOptions = ["--icon", "icons/logo.ico"]
106 | } else if (os.contains('nix') || os.contains('nux') || os.contains('bsd')) {
107 | imageOptions = ["--icon", "icons/logo.png"]
108 | } else if (os.contains('mac')) {
109 | imageOptions = ["--icon", "icons/logo.icns", "--java-options", "\"-XstartOnFirstThread\""]
110 | }
111 | }
112 | }
113 | }
114 |
115 | // Equivalent to the jar task; here for compatibility with gdx-setup.
116 | tasks.register('dist') {
117 | dependsOn['jar']
118 | }
119 |
--------------------------------------------------------------------------------
/core/icons/logo.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/icons/logo.icns
--------------------------------------------------------------------------------
/core/icons/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/icons/logo.ico
--------------------------------------------------------------------------------
/core/icons/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/icons/logo.png
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/FileDialogs.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.files.FileHandle;
5 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
6 | import com.badlogic.gdx.utils.Array;
7 | import org.lwjgl.PointerBuffer;
8 | import org.lwjgl.system.MemoryStack;
9 | import org.lwjgl.util.tinyfd.TinyFileDialogs;
10 |
11 | /**
12 | * A convenience class that provides static methods to open OS native file dialogs.
13 | */
14 | public class FileDialogs {
15 | public static Array openMultipleDialog(String title, String defaultPath, String[] filterPatterns, String filterDescription) {
16 | //fix file path characters
17 | if (UIUtils.isWindows) {
18 | defaultPath = defaultPath.replace("/", "\\");
19 | if (!defaultPath.endsWith("\\")) defaultPath += "\\";
20 | } else {
21 | defaultPath = defaultPath.replace("\\", "/");
22 | if (!defaultPath.endsWith("/")) defaultPath += "/";
23 | }
24 |
25 | MemoryStack stack = MemoryStack.stackPush();
26 |
27 | PointerBuffer filtersPointerBuffer = null;
28 | if (filterPatterns != null) {
29 | filtersPointerBuffer = stack.mallocPointer(filterPatterns.length);
30 |
31 | for (int i = 0; i < filterPatterns.length; i++) {
32 | filtersPointerBuffer.put(stack.UTF8("*." + filterPatterns[i]));
33 | }
34 | filtersPointerBuffer.flip();
35 | }
36 |
37 | var response = TinyFileDialogs.tinyfd_openFileDialog(title, defaultPath, filtersPointerBuffer, filterDescription, true);
38 |
39 | if (response == null) return null;
40 |
41 | var strings = response.split("\\|");
42 | var returnValue = new Array();
43 | for (var string : strings) {
44 | var file = Gdx.files.absolute(string);
45 | if (!file.exists()) continue;
46 | returnValue.add(file);
47 | }
48 |
49 | if (returnValue.size == 0) return null;
50 |
51 | return returnValue;
52 | }
53 |
54 | public static FileHandle openDialog(String title, String defaultPath, String[] filterPatterns, String filterDescription) {
55 | //fix file path characters
56 | if (UIUtils.isWindows) {
57 | defaultPath = defaultPath.replace("/", "\\");
58 | if (!defaultPath.endsWith("\\")) defaultPath += "\\";
59 | } else {
60 | defaultPath = defaultPath.replace("\\", "/");
61 | if (!defaultPath.endsWith("/")) defaultPath += "/";
62 | }
63 |
64 | MemoryStack stack = MemoryStack.stackPush();
65 |
66 | PointerBuffer filtersPointerBuffer = null;
67 | if (filterPatterns != null) {
68 | filtersPointerBuffer = stack.mallocPointer(filterPatterns.length);
69 |
70 | for (int i = 0; i < filterPatterns.length; i++) {
71 | filtersPointerBuffer.put(stack.UTF8("*." + filterPatterns[i]));
72 | }
73 | filtersPointerBuffer.flip();
74 | }
75 |
76 | var response = TinyFileDialogs.tinyfd_openFileDialog(title, defaultPath, filtersPointerBuffer, filterDescription, true);
77 |
78 | if (response == null) return null;
79 |
80 | var file = Gdx.files.absolute(response);
81 |
82 | if (!file.exists()) return null;
83 |
84 | return file;
85 | }
86 |
87 | public static FileHandle saveDialog(String title, String defaultPath, String defaultName, String[] filterPatterns, String filterDescription) {
88 | //fix file path characters
89 | if (UIUtils.isWindows) {
90 | defaultPath = defaultPath.replace("/", "\\");
91 | if (!defaultPath.endsWith("\\")) defaultPath += "\\";
92 | } else {
93 | defaultPath = defaultPath.replace("\\", "/");
94 | if (!defaultPath.endsWith("/")) defaultPath += "/";
95 | }
96 |
97 | MemoryStack stack = MemoryStack.stackPush();
98 |
99 | PointerBuffer filtersPointerBuffer = null;
100 | if (filterPatterns != null) {
101 | filtersPointerBuffer = stack.mallocPointer(filterPatterns.length);
102 |
103 | for (int i = 0; i < filterPatterns.length; i++) {
104 | filtersPointerBuffer.put(stack.UTF8("*." + filterPatterns[i]));
105 | }
106 | filtersPointerBuffer.flip();
107 | }
108 |
109 | var response = TinyFileDialogs.tinyfd_saveFileDialog(title, defaultPath, filtersPointerBuffer, filterDescription);
110 |
111 | if (response == null) return null;
112 |
113 | return Gdx.files.absolute(response);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/ParticlePreview.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.graphics.Color;
5 | import com.badlogic.gdx.math.Vector2;
6 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
7 | import com.badlogic.gdx.utils.ScreenUtils;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.*;
10 | import static com.ray3k.gdxparticleeditor.PreviewSettings.*;
11 |
12 | /**
13 | * This class renders the particle preview.
14 | */
15 | public class ParticlePreview {
16 | private static final Vector2 temp = new Vector2();
17 | public static boolean pause;
18 |
19 | public void render() {
20 | var isDrawing = spriteBatch.isDrawing();
21 | if (!isDrawing) {
22 | spriteBatch.setProjectionMatrix(previewViewport.getCamera().combined);
23 | spriteBatch.begin();
24 | }
25 | spriteBatch.setColor(Color.WHITE);
26 |
27 | //calculate world coordinates
28 | temp.set(previewViewport.getScreenX(), Gdx.graphics.getHeight() - previewViewport.getScreenY());
29 | previewViewport.unproject(temp);
30 | float left = temp.x;
31 | float bottom = temp.y;
32 |
33 | temp.set(previewViewport.getScreenX() + previewViewport.getScreenWidth(), Gdx.graphics.getHeight() - (previewViewport.getScreenY() + previewViewport.getScreenHeight()));
34 | previewViewport.unproject(temp);
35 | float right = temp.x;
36 | float top = temp.y;
37 |
38 | //draw background color
39 | shapeDrawer.setColor(getBackgroundColor());
40 | shapeDrawer.filledRectangle(left, bottom, right - left, top - bottom);
41 |
42 | //draw preview
43 | if (previewImageTexture != null) spriteBatch.draw(previewImageTexture, previewImageX, previewImageY, previewImageWidth, previewImageHeight);
44 |
45 | if (isGridEnabled()) {
46 | //draw major grid
47 | shapeDrawer.setColor(getGridColor());
48 | shapeDrawer.setDefaultLineWidth(2 * previewViewport.getUnitsPerPixel());
49 | for (float x = left - left % getGridMajorGridlines(); x < right; x += getGridMajorGridlines()) {
50 | shapeDrawer.line(x, bottom, x, top);
51 | }
52 | for (float y = bottom - bottom % getGridMajorGridlines(); y < top; y += getGridMajorGridlines()) {
53 | shapeDrawer.line(left, y, right, y);
54 | }
55 |
56 | //draw minor grid
57 | shapeDrawer.setColor(getGridColor());
58 | shapeDrawer.setDefaultLineWidth(1 * previewViewport.getUnitsPerPixel());
59 | for (float x = left - left % getGridMinorGridlines(); x < right; x += getGridMinorGridlines()) {
60 | shapeDrawer.line(x, bottom, x, top);
61 | }
62 | for (float y = bottom - bottom % getGridMinorGridlines(); y < top; y += getGridMinorGridlines()) {
63 | shapeDrawer.line(left, y, right, y);
64 | }
65 | }
66 |
67 | if (isAxesEnabled()) {
68 | //draw axes
69 | shapeDrawer.setColor(getAxesColor());
70 | shapeDrawer.setDefaultLineWidth(3 * previewViewport.getUnitsPerPixel());
71 | if (bottom <= 0) shapeDrawer.line(left, 0, right, 0);
72 | if (left <= 0) shapeDrawer.line(0, bottom, 0, top);
73 | }
74 |
75 | if (!pause) {
76 | particleEffect.update(Gdx.graphics.getDeltaTime() * getDeltaMultiplier());
77 | particleEffect.draw(spriteBatch);
78 | }
79 |
80 | if (!isDrawing) spriteBatch.end();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/SplitPaneSystemCursorListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2022 Raymond Buckley.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.ray3k.gdxparticleeditor;
25 |
26 | import com.badlogic.gdx.Gdx;
27 | import com.badlogic.gdx.graphics.Cursor.SystemCursor;
28 | import com.badlogic.gdx.scenes.scene2d.Actor;
29 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
30 | import com.badlogic.gdx.scenes.scene2d.utils.DragListener;
31 |
32 | /**
33 | * A listener that changes the system cursor when the user enters the actor. The cursor does not change while the user
34 | * is dragging on the actor.
35 | * @author Raymond
36 | */
37 | public class SplitPaneSystemCursorListener extends DragListener {
38 | private boolean draggingCursor;
39 | private SystemCursor systemCursor;
40 |
41 | public SplitPaneSystemCursorListener(SystemCursor systemCursor) {
42 | this.draggingCursor = false;
43 | this.systemCursor = systemCursor;
44 | }
45 |
46 | @Override
47 | public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
48 | if (pointer == -1 && !draggingCursor && event.getListenerActor().equals(event.getTarget())) {
49 | Gdx.graphics.setSystemCursor(SystemCursor.Arrow);
50 | }
51 | }
52 |
53 | @Override
54 | public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
55 | if (!draggingCursor && event.getListenerActor().equals(event.getTarget())) {
56 | Gdx.graphics.setSystemCursor(systemCursor);
57 | }
58 | }
59 |
60 | @Override
61 | public void dragStop(InputEvent event, float x, float y, int pointer) {
62 | if (draggingCursor && !event.getListenerActor().equals(event.getTarget())) {
63 | Gdx.graphics.setSystemCursor(SystemCursor.Arrow);
64 | }
65 | draggingCursor = false;
66 | }
67 |
68 | @Override
69 | public void dragStart(InputEvent event, float x, float y,
70 | int pointer) {
71 | if (!draggingCursor && event.getListenerActor().equals(event.getTarget())) {
72 | draggingCursor = true;
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/SystemCursorListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2022 Raymond Buckley.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | package com.ray3k.gdxparticleeditor;
25 |
26 | import com.badlogic.gdx.Gdx;
27 | import com.badlogic.gdx.graphics.Cursor;
28 | import com.badlogic.gdx.graphics.Cursor.SystemCursor;
29 | import com.badlogic.gdx.scenes.scene2d.Actor;
30 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
31 | import com.badlogic.gdx.scenes.scene2d.utils.Disableable;
32 | import com.badlogic.gdx.scenes.scene2d.utils.DragListener;
33 |
34 | /**
35 | * A listener that changes the system cursor when the user enters the actor.
36 | * @author Raymond
37 | */
38 | public class SystemCursorListener extends DragListener {
39 | public boolean ignoreDisabled;
40 | private boolean draggingCursor;
41 | private SystemCursor systemCursor;
42 |
43 | public SystemCursorListener(SystemCursor systemCursor) {
44 | this.draggingCursor = false;
45 | this.systemCursor = systemCursor;
46 | }
47 |
48 | @Override
49 | public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
50 | if (pointer == -1 && !draggingCursor) {
51 | Gdx.graphics.setSystemCursor(Cursor.SystemCursor.Arrow);
52 | }
53 | }
54 |
55 | @Override
56 | public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
57 | if (!draggingCursor && ignoreDisabled || !isDisabled(event.getListenerActor())) {
58 | Gdx.graphics.setSystemCursor(systemCursor);
59 | }
60 | }
61 |
62 | @Override
63 | public void dragStop(InputEvent event, float x, float y, int pointer) {
64 | if (draggingCursor) {
65 | Gdx.graphics.setSystemCursor(Cursor.SystemCursor.Arrow);
66 | }
67 | draggingCursor = false;
68 | }
69 |
70 | @Override
71 | public void dragStart(InputEvent event, float x, float y, int pointer) {
72 | if (!draggingCursor) {
73 | draggingCursor = true;
74 | }
75 | }
76 |
77 | private boolean isDisabled(Actor actor) {
78 | return actor instanceof Disableable && ((Disableable) actor).isDisabled();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/TextFileApplicationLogger.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * MIT License
3 | *
4 | * Copyright (c) 2022 Raymond Buckley
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | ******************************************************************************/
24 |
25 | package com.ray3k.gdxparticleeditor;
26 |
27 | import com.badlogic.gdx.ApplicationLogger;
28 | import com.badlogic.gdx.files.FileHandle;
29 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
30 |
31 | import java.io.PrintStream;
32 | import java.sql.Timestamp;
33 | import java.util.Date;
34 |
35 | /**
36 | * A logger that saves errors and messages to the provided logFilehandle.
37 | */
38 | public class TextFileApplicationLogger implements ApplicationLogger {
39 | private final FileHandle logFileHandle;
40 |
41 | public TextFileApplicationLogger(FileHandle logFileHandle) {
42 | this.logFileHandle = logFileHandle;
43 | }
44 |
45 | @Override
46 | public void log(String tag, String message) {
47 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
48 |
49 | System.out.println(tag + ": " + message);
50 | }
51 |
52 | @Override
53 | public void log(String tag, String message, Throwable exception) {
54 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
55 | printException(exception);
56 |
57 | System.out.println(tag + ": " + message);
58 | exception.printStackTrace(System.out);
59 | }
60 |
61 | @Override
62 | public void error(String tag, String message) {
63 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
64 |
65 | System.err.println(tag + ": " + message);
66 | }
67 |
68 | @Override
69 | public void error(String tag, String message, Throwable exception) {
70 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
71 | printException(exception);
72 |
73 | System.err.println(tag + ": " + message);
74 | exception.printStackTrace(System.err);
75 | }
76 |
77 | @Override
78 | public void debug(String tag, String message) {
79 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
80 |
81 | System.out.println(tag + ": " + message);
82 | }
83 |
84 | @Override
85 | public void debug(String tag, String message, Throwable exception) {
86 | logFileHandle.writeString("\n" + new Timestamp(System.currentTimeMillis()) + "\n" + retrieveSystemDetails() + tag + ": " + message + "\n", true);
87 | printException(exception);
88 |
89 | System.out.println(tag + ": " + message);
90 | exception.printStackTrace(System.out);
91 | }
92 |
93 | private void printException(Throwable exception) {
94 | PrintStream printStream = new PrintStream(logFileHandle.write(true));
95 | exception.printStackTrace(printStream);
96 | printStream.close();
97 | }
98 |
99 | private String retrieveSystemDetails() {
100 | return "Version: " + Core.version +
101 | "\nOS: " + (UIUtils.isMac ? "Mac" : UIUtils.isWindows ? "Windows" : UIUtils.isLinux ? "Linux" : "Other") + "\n";
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/lwjgl3/Lwjgl3Launcher.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.lwjgl3;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
5 | import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
6 | import com.ray3k.gdxparticleeditor.Core;
7 |
8 | public class Lwjgl3Launcher {
9 | public static void main(String[] args) {
10 | if (StartupHelper.startNewJvmIfRequired()) return;
11 | try {
12 | createApplication();
13 | } catch (Throwable throwable) {
14 | Gdx.app.error(Lwjgl3Launcher.class.getName(), "Error while running application", throwable);
15 | }
16 | }
17 |
18 | private static Lwjgl3Application createApplication() {
19 | var core = new Core();
20 | return new Lwjgl3Application(core, getDefaultConfiguration());
21 | }
22 |
23 | private static Lwjgl3ApplicationConfiguration getDefaultConfiguration() {
24 | Lwjgl3ApplicationConfiguration configuration = new Lwjgl3ApplicationConfiguration();
25 | configuration.setTitle(Core.DEFAULT_WINDOW_TITLE);
26 | configuration.useVsync(true);
27 | configuration.setForegroundFPS(Lwjgl3ApplicationConfiguration.getDisplayMode().refreshRate);
28 | configuration.setBackBufferConfig(8, 8, 8, 8, 16, 0, 10);
29 | configuration.setWindowedMode(1000, 950);
30 | configuration.setWindowIcon("icon128.png", "icon64.png", "icon32.png", "icon16.png");
31 | configuration.setWindowListener(Core.windowListener);
32 | return configuration;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/ExportRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.files.FileHandle;
5 | import com.badlogic.gdx.utils.GdxRuntimeException;
6 | import com.badlogic.gdx.utils.StreamUtils;
7 | import com.ray3k.gdxparticleeditor.Core;
8 | import com.ray3k.gdxparticleeditor.Settings;
9 | import com.ray3k.gdxparticleeditor.widgets.poptables.PopError;
10 | import lombok.Getter;
11 | import lombok.Setter;
12 |
13 | import java.io.FileWriter;
14 | import java.io.IOException;
15 | import java.io.Writer;
16 |
17 | import static com.ray3k.gdxparticleeditor.Core.*;
18 | import static com.ray3k.gdxparticleeditor.Settings.*;
19 | import static com.ray3k.gdxparticleeditor.Utils.showToast;
20 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
21 |
22 | public class ExportRunnable implements Runnable {
23 |
24 | @Getter @Setter
25 | private Runnable onCompletionRunnable;
26 |
27 | @Getter @Setter
28 | private FileHandle exportFileHandle;
29 |
30 | @Getter @Setter
31 | private boolean exportImages;
32 |
33 | @Override
34 | public void run() {
35 | if (preferences.getBoolean(NAME_PRESUME_FILE_EXTENSION, DEFAULT_PRESUME_FILE_EXTENSION) && !exportFileHandle.extension().equals("p"))
36 | exportFileHandle = exportFileHandle.sibling(exportFileHandle.name() + ".p");
37 |
38 | Settings.setDefaultSavePath(exportFileHandle.parent());
39 |
40 | //enable all emitters for export
41 | particleEffect.getEmitters().clear();
42 | for (var entry : activeEmitters.entries()) {
43 | particleEffect.getEmitters().add(entry.key);
44 | }
45 |
46 | var fileError = false;
47 | Writer fileWriter = null;
48 | try {
49 | fileWriter = new FileWriter(exportFileHandle.file());
50 | particleEffect.save(fileWriter);
51 | } catch (IOException e) {
52 | var error = "Error saving particle file.";
53 | var pop = new PopError(error, e.getMessage());
54 | pop.show(foregroundStage);
55 |
56 | Gdx.app.error(Core.class.getName(), error, e);
57 | fileError = true;
58 | } finally {
59 | StreamUtils.closeQuietly(fileWriter);
60 | }
61 |
62 | if (exportImages)
63 | for (var fileHandle : fileHandles.values()) {
64 | if (fileHandle.parent().equals(exportFileHandle.parent())) continue;
65 | try {
66 | fileHandle.copyTo(exportFileHandle.parent().child(fileHandle.name()));
67 | } catch (GdxRuntimeException e) {
68 | var error = "Error copying files to save location.";
69 | var pop = new PopError(error, e.getMessage());
70 | pop.show(foregroundStage);
71 |
72 | Gdx.app.error(Core.class.getName(), error, e);
73 | fileError = true;
74 | }
75 | }
76 |
77 | //reset enabled/disabled emitters
78 | particleEffect.getEmitters().clear();
79 | for (var entry : activeEmitters.entries()) {
80 | if (entry.value) particleEffect.getEmitters().add(entry.key);
81 | }
82 |
83 | effectEmittersPanel.hidePopEmitterControls();
84 | showToast("Exported " + exportFileHandle.name());
85 |
86 | if (!fileError) {
87 | if (onCompletionRunnable != null) Gdx.app.postRunnable(onCompletionRunnable);
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/ImagesRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.files.FileHandle;
5 | import com.badlogic.gdx.scenes.scene2d.Touchable;
6 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
7 | import com.badlogic.gdx.utils.Array;
8 | import com.ray3k.gdxparticleeditor.FileDialogs;
9 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
10 | import com.ray3k.gdxparticleeditor.undo.undoables.ImagesAddUndoable;
11 | import com.ray3k.gdxparticleeditor.widgets.subpanels.ImagesSubPanel;
12 |
13 | import java.util.concurrent.ExecutorService;
14 | import java.util.concurrent.Executors;
15 |
16 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
17 | import static com.ray3k.gdxparticleeditor.Core.stage;
18 | import static com.ray3k.gdxparticleeditor.Settings.getDefaultImagePath;
19 | import static com.ray3k.gdxparticleeditor.Settings.setDefaultImagePath;
20 | import static com.ray3k.gdxparticleeditor.Utils.showToast;
21 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
22 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
23 | import static com.ray3k.gdxparticleeditor.widgets.subpanels.ImagesSubPanel.imagesSubPanel;
24 |
25 | public class ImagesRunnable implements Runnable {
26 |
27 | private static boolean open;
28 |
29 | @Override
30 | public void run () {
31 | if (open)
32 | return;
33 |
34 | if (UIUtils.isMac) openWindow();
35 | else {
36 | ExecutorService service = Executors.newSingleThreadExecutor();
37 | service.execute(this::openWindow);
38 | service.shutdown();
39 | }
40 | }
41 |
42 | private void openWindow() {
43 | open = true;
44 | stage.getRoot().setTouchable(Touchable.disabled);
45 |
46 | if (effectEmittersPanel == null || emitterPropertiesPanel == null) return;
47 |
48 | var selectedFileHandles = FileDialogs.openMultipleDialog("Add images", getDefaultImagePath(), new String[] {"png","jpg","jpeg"}, "Image files (*.png;*.jpg;*.jpeg)");
49 | if (selectedFileHandles == null) {
50 | stage.getRoot().setTouchable(Touchable.enabled);
51 | open = false;
52 | return;
53 | }
54 |
55 | if (selectedFileHandles.size > 0) {
56 | setDefaultImagePath(selectedFileHandles.first().parent());
57 | Gdx.app.postRunnable(() -> {
58 | loadOnMainThread(selectedFileHandles);
59 | });
60 | }
61 |
62 | stage.getRoot().setTouchable(Touchable.enabled);
63 | open = false;
64 | }
65 |
66 | private void loadOnMainThread (Array selectedFileHandles) {
67 | UndoManager.add(new ImagesAddUndoable(selectedEmitter, ImagesSubPanel.imagesSubPanel.list.getSelectedIndex() + 1, selectedFileHandles, "Add Images"));
68 | if (selectedFileHandles.size > 0) {
69 | imagesSubPanel.updateList();
70 | imagesSubPanel.updateDisabled();
71 |
72 | showToast(selectedFileHandles.size == 1 ? "Added image " + selectedFileHandles.first().name() : "Added " + selectedFileHandles.size + " images");
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/MergeRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.files.FileHandle;
5 | import com.badlogic.gdx.scenes.scene2d.Touchable;
6 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
7 | import com.badlogic.gdx.utils.ObjectMap;
8 | import com.badlogic.gdx.utils.OrderedMap;
9 | import com.ray3k.gdxparticleeditor.FileDialogs;
10 | import com.ray3k.gdxparticleeditor.Settings;
11 | import com.ray3k.gdxparticleeditor.Utils;
12 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
13 | import com.ray3k.gdxparticleeditor.undo.undoables.MergeEmitterUndoable;
14 |
15 | import java.util.concurrent.ExecutorService;
16 | import java.util.concurrent.Executors;
17 |
18 | import static com.ray3k.gdxparticleeditor.Core.*;
19 | import static com.ray3k.gdxparticleeditor.Settings.*;
20 | import static com.ray3k.gdxparticleeditor.Utils.showToast;
21 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
22 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
23 |
24 | public class MergeRunnable implements Runnable {
25 |
26 | private static boolean open;
27 |
28 | @Override
29 | public void run () {
30 | if (open)
31 | return;
32 |
33 | if (UIUtils.isMac) openWindow();
34 | else {
35 | ExecutorService service = Executors.newSingleThreadExecutor();
36 | service.execute(this::openWindow);
37 | service.shutdown();
38 | }
39 | }
40 |
41 | private void openWindow() {
42 | open = true;
43 | stage.getRoot().setTouchable(Touchable.disabled);
44 |
45 | if (effectEmittersPanel == null || emitterPropertiesPanel == null) return;
46 |
47 | var useFileExtension = preferences.getBoolean(NAME_PRESUME_FILE_EXTENSION, DEFAULT_PRESUME_FILE_EXTENSION);
48 | var filterPatterns = useFileExtension ? new String[] {"p"} : null;
49 | var fileHandle = FileDialogs.openDialog("Merge", getDefaultSavePath(), filterPatterns, "Particle files (*.p)");
50 |
51 | if (fileHandle != null) {
52 | defaultFileName = fileHandle.name();
53 | Settings.setDefaultSavePath(fileHandle.parent());
54 | Gdx.app.postRunnable(() -> {
55 | loadOnMainThread(fileHandle);
56 | });
57 | }
58 |
59 | stage.getRoot().setTouchable(Touchable.enabled);
60 | open = false;
61 | }
62 |
63 | private void loadOnMainThread (FileHandle fileHandle) {
64 |
65 | var oldActiveEmitters = new OrderedMap<>(activeEmitters);
66 | var oldFileHandles = new ObjectMap<>(fileHandles);
67 | var oldSprites = new ObjectMap<>(sprites);
68 | var oldSelectedIndex = activeEmitters.keys().toArray().indexOf(selectedEmitter, true);
69 |
70 | var completed = Utils.mergeParticle(fileHandle);
71 | if (!completed) return;
72 |
73 | UndoManager.add(MergeEmitterUndoable
74 | .builder()
75 | .oldActiveEmitters(oldActiveEmitters)
76 | .oldFileHandles(oldFileHandles)
77 | .oldSprites(oldSprites)
78 | .oldSelectedIndex(oldSelectedIndex)
79 | .newActiveEmitters(new OrderedMap<>(activeEmitters))
80 | .newFileHandles(new ObjectMap<>(fileHandles))
81 | .newSprites(new ObjectMap<>(sprites))
82 | .newSelectedIndex(activeEmitters.keys().toArray().indexOf(selectedEmitter, true))
83 | .description("Merge Particle Effect")
84 | .build());
85 | effectEmittersPanel.populateEmitters();
86 | effectEmittersPanel.updateDisableableWidgets();
87 | effectEmittersPanel.hidePopEmitterControls();
88 | emitterPropertiesPanel.populateScrollTable(null);
89 | showToast("Merged " + fileHandle.name());
90 |
91 | updateWindowTitle();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/OpenRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.files.FileHandle;
5 | import com.badlogic.gdx.scenes.scene2d.Touchable;
6 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
7 | import com.ray3k.gdxparticleeditor.FileDialogs;
8 | import com.ray3k.gdxparticleeditor.Settings;
9 | import com.ray3k.gdxparticleeditor.Utils;
10 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
11 | import com.ray3k.gdxparticleeditor.widgets.poptables.PopConfirmLoad;
12 |
13 | import java.util.concurrent.ExecutorService;
14 | import java.util.concurrent.Executors;
15 |
16 | import static com.ray3k.gdxparticleeditor.Core.*;
17 | import static com.ray3k.gdxparticleeditor.Settings.*;
18 | import static com.ray3k.gdxparticleeditor.Utils.showToast;
19 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
20 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
21 |
22 | public class OpenRunnable implements Runnable {
23 |
24 | private static boolean open;
25 |
26 | @Override
27 | public void run () {
28 | if (open)
29 | return;
30 |
31 | if (unsavedChangesMade) {
32 | var saveFirstRunnable = new SaveRunnable();
33 | var saveAsFirstRunnable = new SaveAsRunnable();
34 | saveFirstRunnable.setSaveAsRunnable(saveAsFirstRunnable);
35 | saveAsFirstRunnable.setSaveRunnable(saveFirstRunnable);
36 | saveFirstRunnable.setOnCompletionRunnable(this);
37 |
38 | var pop = new PopConfirmLoad(saveFirstRunnable, () -> {
39 | unsavedChangesMade = false;
40 | OpenRunnable.this.run();
41 | });
42 | pop.show(foregroundStage);
43 | return;
44 | }
45 |
46 | if (UIUtils.isMac) openWindow();
47 | else {
48 | ExecutorService service = Executors.newSingleThreadExecutor();
49 | service.execute(this::openWindow);
50 | service.shutdown();
51 | }
52 | }
53 |
54 | private void openWindow() {
55 | open = true;
56 | stage.getRoot().setTouchable(Touchable.disabled);
57 |
58 | if (effectEmittersPanel == null || emitterPropertiesPanel == null)
59 | return;
60 |
61 | var useFileExtension = preferences.getBoolean(NAME_PRESUME_FILE_EXTENSION, DEFAULT_PRESUME_FILE_EXTENSION);
62 | var filterPatterns = useFileExtension ? new String[] {"p"} : null;
63 | var fileHandle = FileDialogs.openDialog("Open", getDefaultSavePath(), filterPatterns, "Particle files (*.p)");
64 |
65 | if (fileHandle != null) {
66 | defaultFileName = fileHandle.name();
67 | Settings.setDefaultSavePath(fileHandle.parent());
68 | Gdx.app.postRunnable(() -> {
69 | loadOnMainThread(fileHandle);
70 | });
71 |
72 | openFileFileHandle = fileHandle;
73 | }
74 |
75 | stage.getRoot().setTouchable(Touchable.enabled);
76 | open = false;
77 | }
78 |
79 | private void loadOnMainThread (FileHandle fileHandle) {
80 | var completed = Utils.loadParticle(fileHandle);
81 |
82 | if (!completed) return;
83 |
84 | selectedEmitter = particleEffect.getEmitters().first();
85 |
86 | effectEmittersPanel.populateEmitters();
87 | effectEmittersPanel.updateDisableableWidgets();
88 | emitterPropertiesPanel.populateScrollTable(null);
89 | effectEmittersPanel.hidePopEmitterControls();
90 | showToast("Opened " + fileHandle.name());
91 |
92 | UndoManager.clear();
93 | unsavedChangesMade = false;
94 | allowClose = true;
95 | updateWindowTitle();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/RedoShortcutRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
4 |
5 | public class RedoShortcutRunnable implements Runnable {
6 |
7 | @Override
8 | public void run () {
9 | if (UndoManager.hasRedo()) {
10 | UndoManager.redo();
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/ReloadImagesRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.ray3k.gdxparticleeditor.Utils;
4 |
5 | public class ReloadImagesRunnable implements Runnable {
6 |
7 | @Override
8 | public void run () {
9 | Utils.reloadSprites();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/SaveAsRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Touchable;
4 | import com.badlogic.gdx.scenes.scene2d.utils.UIUtils;
5 | import com.ray3k.gdxparticleeditor.FileDialogs;
6 |
7 | import java.util.concurrent.ExecutorService;
8 | import java.util.concurrent.Executors;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.*;
11 | import static com.ray3k.gdxparticleeditor.Settings.*;
12 |
13 | public class SaveAsRunnable implements Runnable {
14 |
15 | private static boolean open;
16 | private SaveRunnable saveRunnable;
17 |
18 | public void setSaveRunnable (SaveRunnable runnable) {
19 | saveRunnable = runnable;
20 | }
21 |
22 | @Override
23 | public void run () {
24 | if (open) return;
25 |
26 | if (UIUtils.isMac) openWindow();
27 | else {
28 | ExecutorService service = Executors.newSingleThreadExecutor();
29 | service.execute(this::openWindow);
30 | service.shutdown();
31 | }
32 | }
33 |
34 | private void openWindow() {
35 | open = true;
36 | stage.getRoot().setTouchable(Touchable.disabled);
37 |
38 | var useFileExtension = preferences.getBoolean(NAME_PRESUME_FILE_EXTENSION, DEFAULT_PRESUME_FILE_EXTENSION);
39 | var filterPatterns = useFileExtension ? new String[] {"p"} : null;
40 | var saveHandle = FileDialogs.saveDialog("Save", getDefaultSavePath(), defaultFileName, filterPatterns, "Particle Files (*.p)");
41 |
42 | if (saveHandle != null) {
43 | openFileFileHandle = saveHandle;
44 | saveRunnable.run();
45 | }
46 |
47 | stage.getRoot().setTouchable(Touchable.enabled);
48 | open = false;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/SaveRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.scenes.scene2d.Event;
5 | import com.badlogic.gdx.utils.GdxRuntimeException;
6 | import com.badlogic.gdx.utils.StreamUtils;
7 | import com.ray3k.gdxparticleeditor.Core;
8 | import com.ray3k.gdxparticleeditor.Settings;
9 | import com.ray3k.gdxparticleeditor.widgets.poptables.PopError;
10 | import com.ray3k.stripe.PopTable.TableShowHideListener;
11 | import lombok.Getter;
12 | import lombok.Setter;
13 |
14 | import java.io.FileWriter;
15 | import java.io.IOException;
16 | import java.io.Writer;
17 |
18 | import static com.ray3k.gdxparticleeditor.Core.*;
19 | import static com.ray3k.gdxparticleeditor.Settings.*;
20 | import static com.ray3k.gdxparticleeditor.Utils.showToast;
21 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
22 |
23 | public class SaveRunnable implements Runnable {
24 |
25 | private SaveAsRunnable saveAsRunnable;
26 | @Getter @Setter
27 | private Runnable onCompletionRunnable;
28 |
29 | public void setSaveAsRunnable (SaveAsRunnable runnable) {
30 | saveAsRunnable = runnable;
31 | }
32 |
33 | @Override
34 | public void run () {
35 | if (openFileFileHandle != null) {
36 | if (preferences.getBoolean(NAME_PRESUME_FILE_EXTENSION, DEFAULT_PRESUME_FILE_EXTENSION) && !openFileFileHandle.extension().equals("p"))
37 | openFileFileHandle = openFileFileHandle.sibling(openFileFileHandle.name() + ".p");
38 |
39 | Settings.setDefaultSavePath(openFileFileHandle.parent());
40 | defaultFileName = openFileFileHandle.name();
41 |
42 | //enable all emitters for export
43 | particleEffect.getEmitters().clear();
44 | for (var entry : activeEmitters.entries()) {
45 | particleEffect.getEmitters().add(entry.key);
46 | }
47 |
48 | var fileError = false;
49 | Writer fileWriter = null;
50 | try {
51 | fileWriter = new FileWriter(openFileFileHandle.file());
52 | particleEffect.save(fileWriter);
53 | } catch (IOException e) {
54 | var error = "Error saving particle file.";
55 | var pop = new PopError(error, e.getMessage());
56 | pop.show(foregroundStage);
57 |
58 | Gdx.app.error(Core.class.getName(), error, e);
59 | fileError = true;
60 | } finally {
61 | StreamUtils.closeQuietly(fileWriter);
62 | }
63 |
64 | if (preferences.getBoolean(NAME_EXPORT_IMAGES, DEFAULT_EXPORT_IMAGES)) for (var fileHandle : fileHandles.values()) {
65 | if (fileHandle.parent().equals(openFileFileHandle.parent())) continue;
66 | try {
67 | fileHandle.copyTo(openFileFileHandle.parent().child(fileHandle.name()));
68 | } catch (GdxRuntimeException e) {
69 | var error = "Error copying files to save location.";
70 | var pop = new PopError(error, e.getMessage());
71 | pop.show(foregroundStage);
72 |
73 | Gdx.app.error(Core.class.getName(), error, e);
74 | fileError = true;
75 | }
76 | }
77 |
78 | //reset enabled/disabled emitters
79 | particleEffect.getEmitters().clear();
80 | for (var entry : activeEmitters.entries()) {
81 | if (entry.value) particleEffect.getEmitters().add(entry.key);
82 | }
83 |
84 | effectEmittersPanel.hidePopEmitterControls();
85 | showToast("Saved " + openFileFileHandle.name());
86 |
87 | if (!fileError) {
88 | unsavedChangesMade = false;
89 | allowClose = true;
90 | Core.updateWindowTitle();
91 | if (onCompletionRunnable != null) Gdx.app.postRunnable(onCompletionRunnable);
92 | }
93 | } else {
94 | saveAsRunnable.run();
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/SwitchModeRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.badlogic.gdx.utils.Align;
4 | import com.ray3k.gdxparticleeditor.Core;
5 | import com.ray3k.gdxparticleeditor.Settings;
6 | import com.ray3k.gdxparticleeditor.shortcuts.ShortcutManager;
7 | import com.ray3k.gdxparticleeditor.widgets.tables.ClassicTable;
8 | import com.ray3k.gdxparticleeditor.widgets.tables.WizardTable;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.shortcutManager;
11 | import static com.ray3k.gdxparticleeditor.PresetActions.transition;
12 |
13 | public class SwitchModeRunnable implements Runnable {
14 |
15 | @Override
16 | public void run () {
17 | if (Core.openTable.equals("Wizard") && (ClassicTable.classicTable == null || ClassicTable.classicTable.getStage() == null)) {
18 | Core.openTable = "Classic";
19 | transition(WizardTable.wizardTable, new ClassicTable(), Align.top);
20 | shortcutManager.setDisabled(false);
21 | ShortcutManager.setScope(Settings.CLASSIC_SCOPE);
22 | } else if (Core.openTable.equals("Classic") && (WizardTable.wizardTable == null || WizardTable.wizardTable.getStage() == null)) {
23 | Core.openTable = "Wizard";
24 | transition(ClassicTable.classicTable, new WizardTable(), Align.top);
25 | shortcutManager.setDisabled(false);
26 | ShortcutManager.setScope(Settings.WIZARD_SCOPE);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/runnables/UndoShortcutRunnable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.runnables;
2 |
3 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
4 |
5 | public class UndoShortcutRunnable implements Runnable {
6 |
7 | @Override
8 | public void run () {
9 | if (UndoManager.hasUndo()) {
10 | UndoManager.undo();
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/shortcuts/InvalidShortcutException.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.shortcuts;
2 |
3 | /**
4 | * An exception thrown when the user enters an invalid key combination.
5 | */
6 | public class InvalidShortcutException extends RuntimeException {
7 |
8 | public InvalidShortcutException (String message) {
9 | super(message);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/shortcuts/KeybindReference.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.shortcuts;
2 |
3 | import static com.ray3k.gdxparticleeditor.Utils.EMPTY_KEYBIND;
4 |
5 | /**
6 | * A pair of integer arrays that hold a primary and secondary keybind for a shortcut.
7 | */
8 | public class KeybindReference {
9 |
10 | private final int[] primaryKeybind;
11 | private final int[] secondaryKeybind;
12 |
13 | public KeybindReference (int[] primaryKeybind, int[] secondaryKeybind) {
14 | this.primaryKeybind = primaryKeybind;
15 | this.secondaryKeybind = secondaryKeybind;
16 | }
17 |
18 | public int[] getPrimaryKeybind() {
19 | return primaryKeybind != null ? primaryKeybind : EMPTY_KEYBIND;
20 | }
21 |
22 | public int[] getSecondaryKeybind() {
23 | return secondaryKeybind != null ? secondaryKeybind : EMPTY_KEYBIND;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/shortcuts/Shortcut.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.shortcuts;
2 |
3 | import java.util.Objects;
4 |
5 | import static com.ray3k.gdxparticleeditor.Utils.EMPTY_KEYBIND;
6 |
7 | /**
8 | * A Shortcut consists of a primary and secondary keybind associated with a Runnable action. A name and description
9 | * are stored for display in the settings UI.
10 | */
11 | public class Shortcut {
12 |
13 | private int[] primaryKeybind;
14 | private int[] secondaryKeybind;
15 | private int primaryKeybindPacked;
16 | private int secondaryKeybindPacked;
17 | private final Runnable runnable;
18 | private final String name;
19 | private final String description;
20 | private int scope;
21 |
22 | public Shortcut (String name, String description, Runnable runnable) {
23 | this.name = name;
24 | this.description = description;
25 | this.runnable = runnable;
26 | }
27 |
28 | public Shortcut setScope (int scope) {
29 | this.scope = scope;
30 | return this;
31 | }
32 |
33 | public int getScope() {
34 | return scope;
35 | }
36 |
37 | public Runnable getRunnable() {
38 | return runnable;
39 | }
40 |
41 | public String getName() {
42 | return name;
43 | }
44 |
45 | public String getDescription() {
46 | return description;
47 | }
48 |
49 | public Shortcut setPrimaryKeybind(int[] keybind, int packed) {
50 | primaryKeybind = keybind;
51 | primaryKeybindPacked = packed;
52 | return this;
53 | }
54 | public int[] getPrimaryKeybind() {
55 | return primaryKeybind != null ? primaryKeybind : EMPTY_KEYBIND;
56 | }
57 |
58 | public int getPrimaryKeybindPacked () {
59 | return primaryKeybindPacked;
60 | }
61 |
62 | public Shortcut setSecondaryKeybind (int[] keybind, int packed) {
63 | secondaryKeybind = keybind;
64 | secondaryKeybindPacked = packed;
65 | return this;
66 | }
67 |
68 | public int[] getSecondaryKeybind() {
69 | return secondaryKeybind != null ? secondaryKeybind : EMPTY_KEYBIND;
70 | }
71 |
72 | public int getSecondaryKeybindPacked() {
73 | return secondaryKeybindPacked;
74 | }
75 |
76 | @Override
77 | public boolean equals (Object o) {
78 | if (this == o)
79 | return true;
80 | if (o == null || getClass() != o.getClass())
81 | return false;
82 | Shortcut shortcut = (Shortcut)o;
83 | return scope == shortcut.scope && runnable.equals(shortcut.runnable) && name.equals(shortcut.name) && description.equals(
84 | shortcut.description);
85 | }
86 |
87 | @Override
88 | public int hashCode () {
89 | return Objects.hash(runnable, name, description, scope);
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/UndoManager.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo;
2 |
3 | import com.badlogic.gdx.utils.Array;
4 | import com.ray3k.gdxparticleeditor.Core;
5 | import com.ray3k.gdxparticleeditor.Utils;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.allowClose;
8 |
9 | /**
10 | * The UndoManager is a system to handle undo/redo in the app. The description of the currently primed undo/redo is
11 | * provided. The undoIndex indicates where in the history that the user is currently at. Certain actions will wipe the
12 | * undo history, such as loading a new effect. Adding a new undoable will erase all undoables in the history past the
13 | * current undoIndex.
14 | */
15 | public class UndoManager {
16 | public final static Array undoables = new Array<>();
17 | public static int undoIndex = -1;
18 |
19 | public static void add(Undoable undoable) {
20 | if (hasRedo()) undoables.removeRange(undoIndex + 1, undoables.size - 1);
21 |
22 | undoables.add(undoable);
23 | undoable.start();
24 | undoIndex = undoables.size - 1;
25 | Utils.refreshUndoButtons();
26 |
27 | Core.unsavedChangesMade = true;
28 | allowClose = false;
29 | Core.updateWindowTitle();
30 | }
31 |
32 | public static String getUndoDescription() {
33 | return hasUndo() ? undoables.get(undoIndex).getDescription() : "";
34 | }
35 |
36 | public static String getRedoDescription() {
37 | return hasRedo() ? undoables.get(undoIndex + 1).getDescription() : "";
38 | }
39 |
40 | public static boolean hasUndo() {
41 | return undoIndex >= 0;
42 | }
43 |
44 | public static boolean hasRedo() {
45 | return undoables.size > 0 && undoIndex < undoables.size - 1;
46 | }
47 |
48 | public static void undo() {
49 | if (!hasUndo()) return;
50 | var undoable = undoables.get(undoIndex--);
51 | Utils.showToast("Undo " + undoable.getDescription());
52 | undoable.undo();
53 | Utils.refreshUndoButtons();
54 | Core.unsavedChangesMade = true;
55 | allowClose = false;
56 | Core.updateWindowTitle();
57 | }
58 |
59 | public static void redo() {
60 | if (!hasRedo()) return;
61 | var undoable = undoables.get(++undoIndex);
62 | Utils.showToast("Redo " + undoable.getDescription());
63 | undoable.redo();
64 | Utils.refreshUndoButtons();
65 | Core.unsavedChangesMade = true;
66 | allowClose = false;
67 | Core.updateWindowTitle();
68 | }
69 |
70 | public static void clear() {
71 | undoables.clear();
72 | undoIndex = -1;
73 | Utils.refreshUndoButtons();
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/Undoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo;
2 |
3 | /**
4 | * Undoable is an interface used by the UndoManager to allow the user to undo/redo actions in the interface. This
5 | * interface also provides the description when the user hovers over the undo/redo buttons.
6 | */
7 | public interface Undoable {
8 | void undo();
9 | void redo();
10 | void start();
11 | String getDescription();
12 | }
13 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/CountMaxUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
8 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
11 |
12 | /**
13 | * Undoable for increasing the maximum particle count for the emitter.
14 | */
15 | @AllArgsConstructor
16 | public class CountMaxUndoable implements Undoable {
17 | private ParticleEmitter emitter;
18 | private int newValue;
19 | private int oldValue;
20 |
21 | @Override
22 | public void undo() {
23 | selectedEmitter = emitter;
24 |
25 | emitter.setMaxParticleCount(oldValue);
26 | refreshDisplay();
27 | }
28 |
29 | @Override
30 | public void redo() {
31 | selectedEmitter = emitter;
32 | emitter.setMaxParticleCount(newValue);
33 | refreshDisplay();
34 | }
35 |
36 | @Override
37 | public void start() {
38 | emitter.setMaxParticleCount(newValue);
39 | }
40 |
41 | @Override
42 | public String getDescription() {
43 | return "change Count max";
44 | }
45 |
46 | private void refreshDisplay() {
47 | effectEmittersPanel.populateEmitters();
48 | emitterPropertiesPanel.populateScrollTable(null);
49 | particleEffect.reset();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/CountMinUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
8 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
11 |
12 | /**
13 | * Undoable for increasing the minimum particle count for the emitter.
14 | */
15 | @AllArgsConstructor
16 | public class CountMinUndoable implements Undoable {
17 | private ParticleEmitter emitter;
18 | private int newValue;
19 | private int oldValue;
20 |
21 | @Override
22 | public void undo() {
23 | selectedEmitter = emitter;
24 |
25 | emitter.setMinParticleCount(oldValue);
26 | refreshDisplay();
27 | }
28 |
29 | @Override
30 | public void redo() {
31 | selectedEmitter = emitter;
32 |
33 | emitter.setMinParticleCount(newValue);
34 | refreshDisplay();
35 | }
36 |
37 | @Override
38 | public void start() {
39 | emitter.setMinParticleCount(newValue);
40 | }
41 |
42 | @Override
43 | public String getDescription() {
44 | return "change Count min";
45 | }
46 |
47 | private void refreshDisplay() {
48 | effectEmittersPanel.populateEmitters();
49 | emitterPropertiesPanel.populateScrollTable(null);
50 | particleEffect.reset();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/DeleteEmitterUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.*;
8 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
10 |
11 | /**
12 | * Undoable to delete the selected emitter.
13 | */
14 | @AllArgsConstructor
15 | public class DeleteEmitterUndoable implements Undoable {
16 | private ParticleEmitter emitter;
17 | private int index;
18 | private String description;
19 |
20 | @Override
21 | public void undo() {
22 | particleEffect.getEmitters().add(emitter);
23 | activeEmitters.put(emitter, true);
24 | activeEmitters.orderedKeys().removeIndex(activeEmitters.orderedKeys().size - 1);
25 | activeEmitters.orderedKeys().insert(index, emitter);
26 | selectedEmitter = emitter;
27 | refreshDisplay();
28 | }
29 |
30 | @Override
31 | public void redo() {
32 | particleEffect.getEmitters().removeValue(emitter, true);
33 | activeEmitters.remove(emitter);
34 | selectedEmitter = activeEmitters.orderedKeys().get(Math.min(index, activeEmitters.orderedKeys().size - 1));
35 | refreshDisplay();
36 | }
37 |
38 | @Override
39 | public void start() {
40 | particleEffect.getEmitters().removeValue(emitter, true);
41 | activeEmitters.remove(emitter);
42 | selectedEmitter = activeEmitters.orderedKeys().get(Math.min(index, activeEmitters.orderedKeys().size - 1));
43 | }
44 |
45 | @Override
46 | public String getDescription() {
47 | return description;
48 | }
49 |
50 | private void refreshDisplay() {
51 | effectEmittersPanel.populateEmitters();
52 | effectEmittersPanel.updateDisableableWidgets();
53 | emitterPropertiesPanel.populateScrollTable(null);
54 | particleEffect.reset();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/DualScaledNumericValueRelativeUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.ScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
10 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
13 |
14 | /**
15 | * Undoable to set the relative value of a ScaledNumericValue pair (ex. Size)
16 | */
17 | @Data
18 | @AllArgsConstructor
19 | public class DualScaledNumericValueRelativeUndoable implements Undoable {
20 | private ParticleEmitter emitter;
21 | private ScaledNumericValue xValue;
22 | private ScaledNumericValue yValue;
23 | private boolean active;
24 | private String description;
25 |
26 | @Override
27 | public void undo() {
28 | selectedEmitter = emitter;
29 |
30 | xValue.setRelative(!active);
31 | yValue.setRelative(!active);
32 | refreshDisplay();
33 | }
34 |
35 | @Override
36 | public void redo() {
37 | selectedEmitter = emitter;
38 |
39 | xValue.setRelative(active);
40 | yValue.setRelative(active);
41 | refreshDisplay();
42 | }
43 |
44 | @Override
45 | public void start() {
46 | xValue.setRelative(active);
47 | yValue.setRelative(active);
48 | }
49 |
50 | @Override
51 | public String getDescription() {
52 | return description;
53 | }
54 |
55 | private void refreshDisplay() {
56 | effectEmittersPanel.populateEmitters();
57 | emitterPropertiesPanel.populateScrollTable(null);
58 | particleEffect.reset();
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/DualScaledNumericValueUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.ScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.Builder;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
9 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to set the value of a ScaledNumericValue pair (ex. Size)
15 | */
16 | @Builder(toBuilder = true)
17 | public class DualScaledNumericValueUndoable implements Undoable {
18 | private ParticleEmitter emitter;
19 | public final ScaledNumericValue newXvalue = new ScaledNumericValue();
20 | public final ScaledNumericValue oldXvalue = new ScaledNumericValue();
21 | private ScaledNumericValue xValue;
22 | public final ScaledNumericValue newYvalue = new ScaledNumericValue();
23 | public final ScaledNumericValue oldYvalue = new ScaledNumericValue();
24 | private ScaledNumericValue yValue;
25 | private String description;
26 |
27 | @Override
28 | public void undo() {
29 | selectedEmitter = emitter;
30 |
31 | xValue.set(oldXvalue);
32 | yValue.set(oldYvalue);
33 | refreshDisplay();
34 | }
35 |
36 | @Override
37 | public void redo() {
38 | selectedEmitter = emitter;
39 |
40 | xValue.set(newXvalue);
41 | yValue.set(newYvalue);
42 | refreshDisplay();
43 | }
44 |
45 | @Override
46 | public void start() {
47 | xValue.set(newXvalue);
48 | yValue.set(newYvalue);
49 | }
50 |
51 | @Override
52 | public String getDescription() {
53 | return description;
54 | }
55 |
56 | private void refreshDisplay() {
57 | effectEmittersPanel.populateEmitters();
58 | emitterPropertiesPanel.populateScrollTable(null);
59 | particleEffect.reset();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ImagesAddUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.Texture;
5 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
6 | import com.badlogic.gdx.graphics.g2d.Sprite;
7 | import com.badlogic.gdx.utils.Array;
8 | import com.badlogic.gdx.utils.ObjectMap;
9 | import com.ray3k.gdxparticleeditor.Utils;
10 | import com.ray3k.gdxparticleeditor.undo.Undoable;
11 | import lombok.AllArgsConstructor;
12 |
13 | import static com.ray3k.gdxparticleeditor.Core.*;
14 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
15 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
16 |
17 | /**
18 | * Undoable to add images to the emitter.
19 | */
20 | @AllArgsConstructor
21 | public class ImagesAddUndoable implements Undoable {
22 | private ParticleEmitter emitter;
23 | private int imageInsertIndex;
24 | private Array selectedFileHandles;
25 | private String description;
26 | private final Array newImagePaths = new Array<>();
27 | private final ObjectMap newFileHandles = new ObjectMap<>();
28 | private final ObjectMap newSpriteMap = new ObjectMap<>();
29 | private final Array newSprites = new Array<>();
30 |
31 | @Override
32 | public void undo() {
33 | selectedEmitter = emitter;
34 |
35 | emitter.getImagePaths().removeRange(imageInsertIndex, imageInsertIndex + newImagePaths.size - 1);
36 | Utils.removeUnusedImageFiles();
37 | for (var newSprite : newSpriteMap) {
38 | sprites.remove(newSprite.key);
39 | }
40 | emitter.getSprites().removeRange(imageInsertIndex, imageInsertIndex + newSprites.size - 1);
41 | refreshDisplay();
42 | }
43 |
44 | @Override
45 | public void redo() {
46 | selectedEmitter = emitter;
47 |
48 | for (int i = 0; i < newImagePaths.size; i++) {
49 | emitter.getImagePaths().insert(imageInsertIndex + i, newImagePaths.get(i));
50 | }
51 | fileHandles.putAll(newFileHandles);
52 | sprites.putAll(newSpriteMap);
53 | for (int i = 0; i < newSprites.size; i++) {
54 | emitter.getSprites().insert(imageInsertIndex + i, newSprites.get(i));
55 | }
56 | refreshDisplay();
57 | }
58 |
59 | @Override
60 | public void start() {
61 | for (var fileHandle : selectedFileHandles) {
62 | var path = fileHandle.name();
63 | newImagePaths.add(path);
64 | newFileHandles.put(path, fileHandle);
65 | var sprite = new Sprite(new Texture(fileHandle));
66 | newSpriteMap.put(path, sprite);
67 | newSprites.add(sprite);
68 | }
69 |
70 | for (int i = 0; i < newImagePaths.size; i++) {
71 | emitter.getImagePaths().insert(imageInsertIndex + i, newImagePaths.get(i));
72 | }
73 | fileHandles.putAll(newFileHandles);
74 | sprites.putAll(newSpriteMap);
75 | for (int i = 0; i < newSprites.size; i++) {
76 | emitter.getSprites().insert(imageInsertIndex + i, newSprites.get(i));
77 | }
78 | }
79 |
80 | @Override
81 | public String getDescription() {
82 | return description;
83 | }
84 |
85 | private void refreshDisplay() {
86 | effectEmittersPanel.populateEmitters();
87 | emitterPropertiesPanel.populateScrollTable(null);
88 | particleEffect.reset();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ImagesMoveUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
8 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
11 |
12 | /**
13 | * Undoable to rearrange the images in the emitter.
14 | */
15 | @AllArgsConstructor
16 | public class ImagesMoveUndoable implements Undoable {
17 | private ParticleEmitter emitter;
18 | private int oldIndex;
19 | private int newIndex;
20 | private String description;
21 |
22 | @Override
23 | public void undo() {
24 | selectedEmitter = emitter;
25 |
26 | var paths = emitter.getImagePaths();
27 | var sprites = emitter.getSprites();
28 | var path = paths.get(newIndex);
29 | var sprite = sprites.get(newIndex);
30 | paths.removeIndex(newIndex);
31 | sprites.removeIndex(newIndex);
32 | paths.insert(oldIndex, path);
33 | sprites.insert(oldIndex, sprite);
34 | refreshDisplay();
35 | }
36 |
37 | @Override
38 | public void redo() {
39 | selectedEmitter = emitter;
40 |
41 | var paths = emitter.getImagePaths();
42 | var sprites = emitter.getSprites();
43 | var path = paths.get(oldIndex);
44 | var sprite = sprites.get(oldIndex);
45 | paths.removeIndex(oldIndex);
46 | sprites.removeIndex(oldIndex);
47 | paths.insert(newIndex, path);
48 | sprites.insert(newIndex, sprite);
49 | refreshDisplay();
50 | }
51 |
52 | @Override
53 | public void start() {
54 | var paths = emitter.getImagePaths();
55 | var sprites = emitter.getSprites();
56 | var path = paths.get(oldIndex);
57 | var sprite = sprites.get(oldIndex);
58 | paths.removeIndex(oldIndex);
59 | sprites.removeIndex(oldIndex);
60 | paths.insert(newIndex, path);
61 | sprites.insert(newIndex, sprite);
62 | }
63 |
64 | @Override
65 | public String getDescription() {
66 | return description;
67 | }
68 |
69 | private void refreshDisplay() {
70 | effectEmittersPanel.populateEmitters();
71 | emitterPropertiesPanel.populateScrollTable(null);
72 | particleEffect.reset();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ImagesRemoveUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
5 | import com.badlogic.gdx.graphics.g2d.Sprite;
6 | import com.ray3k.gdxparticleeditor.Utils;
7 | import com.ray3k.gdxparticleeditor.undo.Undoable;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.*;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to remove images from the emitter.
15 | */
16 | public class ImagesRemoveUndoable implements Undoable {
17 | private ParticleEmitter emitter;
18 | private String path;
19 | private FileHandle fileHandle;
20 | private Sprite sprite;
21 | private String description;
22 | private int index;
23 |
24 | public ImagesRemoveUndoable(ParticleEmitter emitter, String path, FileHandle fileHandle, Sprite sprite,
25 | String description) {
26 | this.emitter = emitter;
27 | this.path = path;
28 | this.fileHandle = fileHandle;
29 | this.sprite = sprite;
30 | this.description = description;
31 | index = emitter.getSprites().indexOf(sprite, true);
32 | }
33 |
34 | @Override
35 | public void undo() {
36 | selectedEmitter = emitter;
37 |
38 | emitter.getImagePaths().insert(index, path);
39 | fileHandles.put(path, fileHandle);
40 | sprites.put(path, sprite);
41 | emitter.getSprites().insert(index, sprite);
42 | refreshDisplay();
43 | }
44 |
45 | @Override
46 | public void redo() {
47 | selectedEmitter = emitter;
48 |
49 | emitter.getImagePaths().removeValue(path, false);
50 | Utils.removeUnusedImageFiles();
51 | sprites.remove(path);
52 | emitter.getSprites().removeValue(sprite, true);
53 | refreshDisplay();
54 | }
55 |
56 | @Override
57 | public void start() {
58 | emitter.getImagePaths().removeValue(path, false);
59 | Utils.removeUnusedImageFiles();
60 | sprites.remove(path);
61 | emitter.getSprites().removeValue(sprite, true);
62 | }
63 |
64 | @Override
65 | public String getDescription() {
66 | return description;
67 | }
68 |
69 | private void refreshDisplay() {
70 | effectEmittersPanel.populateEmitters();
71 | emitterPropertiesPanel.populateScrollTable(null);
72 | particleEffect.reset();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ImagesSpriteModeUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.SpriteMode;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
9 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to change the sprite mode of the emitter.
15 | */
16 | @AllArgsConstructor
17 | public class ImagesSpriteModeUndoable implements Undoable {
18 | private ParticleEmitter emitter;
19 | private SpriteMode spriteMode;
20 | private SpriteMode oldSpriteMode;
21 | private String description;
22 |
23 | @Override
24 | public void undo() {
25 | selectedEmitter = emitter;
26 |
27 | emitter.setSpriteMode(oldSpriteMode);
28 | refreshDisplay();
29 | }
30 |
31 | @Override
32 | public void redo() {
33 | selectedEmitter = emitter;
34 |
35 | emitter.setSpriteMode(spriteMode);
36 | refreshDisplay();
37 | }
38 |
39 | @Override
40 | public void start() {
41 | emitter.setSpriteMode(spriteMode);
42 | }
43 |
44 | @Override
45 | public String getDescription() {
46 | return description;
47 | }
48 |
49 | private void refreshDisplay() {
50 | effectEmittersPanel.populateEmitters();
51 | emitterPropertiesPanel.populateScrollTable(null);
52 | particleEffect.reset();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/MergeEmitterUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.files.FileHandle;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
5 | import com.badlogic.gdx.graphics.g2d.Sprite;
6 | import com.badlogic.gdx.utils.ObjectMap;
7 | import com.badlogic.gdx.utils.OrderedMap;
8 | import com.ray3k.gdxparticleeditor.undo.Undoable;
9 | import lombok.Builder;
10 |
11 | import static com.ray3k.gdxparticleeditor.Core.*;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
13 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
14 |
15 | /**
16 | * Undoable to merge a new list of emitters with the existing emitters.
17 | */
18 | @Builder
19 | public class MergeEmitterUndoable implements Undoable {
20 | private OrderedMap oldActiveEmitters;
21 | private ObjectMap oldFileHandles;
22 | private ObjectMap oldSprites;
23 | private int oldSelectedIndex;
24 | private OrderedMap newActiveEmitters;
25 | private ObjectMap newFileHandles;
26 | private ObjectMap newSprites;
27 | private int newSelectedIndex;
28 | private String description;
29 |
30 | @Override
31 | public void undo() {
32 | particleEffect.getEmitters().clear();
33 |
34 | activeEmitters.clear();
35 | for (var oldActiveEmitter : oldActiveEmitters) {
36 | activeEmitters.put(oldActiveEmitter.key, oldActiveEmitter.value);
37 | if (oldActiveEmitter.value) particleEffect.getEmitters().add(oldActiveEmitter.key);
38 | }
39 |
40 | fileHandles.clear();
41 | fileHandles.putAll(oldFileHandles);
42 |
43 | sprites.clear();
44 | sprites.putAll(oldSprites);
45 |
46 | selectedEmitter = activeEmitters.orderedKeys().get(oldSelectedIndex);
47 |
48 | refreshDisplay();
49 | }
50 |
51 | @Override
52 | public void redo() {
53 | particleEffect.getEmitters().clear();
54 |
55 | activeEmitters.clear();
56 | for (var newActiveEmitter : newActiveEmitters) {
57 | activeEmitters.put(newActiveEmitter.key, newActiveEmitter.value);
58 | if (newActiveEmitter.value) particleEffect.getEmitters().add(newActiveEmitter.key);
59 | }
60 |
61 | fileHandles.clear();
62 | fileHandles.putAll(newFileHandles);
63 |
64 | sprites.clear();
65 | sprites.putAll(newSprites);
66 |
67 | selectedEmitter = activeEmitters.orderedKeys().get(newSelectedIndex);
68 |
69 | refreshDisplay();
70 | }
71 |
72 | @Override
73 | public void start() {
74 | selectedEmitter = activeEmitters.orderedKeys().get(newSelectedIndex);
75 | particleEffect.reset();
76 | }
77 |
78 | @Override
79 | public String getDescription() {
80 | return description;
81 | }
82 |
83 | private void refreshDisplay() {
84 | effectEmittersPanel.populateEmitters();
85 | effectEmittersPanel.updateDisableableWidgets();
86 | emitterPropertiesPanel.populateScrollTable(null);
87 | particleEffect.reset();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/MoveEmitterUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.*;
8 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
10 |
11 | /**
12 | * Undoable to rearrange the emitters in the particle effect.
13 | */
14 | @AllArgsConstructor
15 | public class MoveEmitterUndoable implements Undoable {
16 | private ParticleEmitter emitter;
17 | private int oldIndex;
18 | private int newIndex;
19 | private String description;
20 |
21 | @Override
22 | public void undo() {
23 | activeEmitters.orderedKeys().removeIndex(newIndex);
24 | activeEmitters.orderedKeys().insert(oldIndex, emitter);
25 |
26 | particleEffect.getEmitters().clear();
27 | for (var entry : activeEmitters.entries()) {
28 | if (entry.value) particleEffect.getEmitters().add(entry.key);
29 | }
30 |
31 | selectedEmitter = emitter;
32 | refreshDisplay();
33 | }
34 |
35 | @Override
36 | public void redo() {
37 | activeEmitters.orderedKeys().removeIndex(oldIndex);
38 | activeEmitters.orderedKeys().insert(newIndex, emitter);
39 |
40 | particleEffect.getEmitters().clear();
41 | for (var entry : activeEmitters.entries()) {
42 | if (entry.value) particleEffect.getEmitters().add(entry.key);
43 | }
44 |
45 | selectedEmitter = emitter;
46 | refreshDisplay();
47 | }
48 |
49 | @Override
50 | public void start() {
51 | activeEmitters.orderedKeys().removeIndex(oldIndex);
52 | activeEmitters.orderedKeys().insert(newIndex, emitter);
53 |
54 | particleEffect.getEmitters().clear();
55 | for (var entry : activeEmitters.entries()) {
56 | if (entry.value) particleEffect.getEmitters().add(entry.key);
57 | }
58 |
59 | selectedEmitter = emitter;
60 | }
61 |
62 | @Override
63 | public String getDescription() {
64 | return description;
65 | }
66 |
67 | private void refreshDisplay() {
68 | effectEmittersPanel.populateEmitters();
69 | emitterPropertiesPanel.populateScrollTable(null);
70 | particleEffect.reset();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/NewEmitterUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.*;
8 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
10 |
11 | /**
12 | * Undoable to create a new emitter and add it to the particle effect.
13 | */
14 | @AllArgsConstructor
15 | public class NewEmitterUndoable implements Undoable {
16 | private ParticleEmitter emitter;
17 | private String description;
18 |
19 | @Override
20 | public void undo() {
21 | var index = particleEffect.getEmitters().indexOf(emitter, true);
22 | particleEffect.getEmitters().removeIndex(index);
23 | activeEmitters.remove(emitter);
24 | selectedEmitter = particleEffect.getEmitters().get(Math.min(index, activeEmitters.orderedKeys().size - 1));
25 | refreshDisplay();
26 | }
27 |
28 | @Override
29 | public void redo() {
30 | particleEffect.getEmitters().add(emitter);
31 | activeEmitters.put(emitter, true);
32 | selectedEmitter = emitter;
33 | refreshDisplay();
34 | }
35 |
36 | @Override
37 | public void start() {
38 | particleEffect.getEmitters().add(emitter);
39 | activeEmitters.put(emitter, true);
40 | selectedEmitter = emitter;
41 | }
42 |
43 | @Override
44 | public String getDescription() {
45 | return description;
46 | }
47 |
48 | private void refreshDisplay() {
49 | effectEmittersPanel.populateEmitters();
50 | effectEmittersPanel.updateDisableableWidgets();
51 | emitterPropertiesPanel.populateScrollTable(null);
52 | particleEffect.reset();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/OptionsUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Data;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
10 |
11 | /**
12 | * Undoable to change the options of the particle effect.
13 | */
14 | @Data
15 | @AllArgsConstructor
16 | public class OptionsUndoable implements Undoable {
17 | private ParticleEmitter emitter;
18 | public enum Type {
19 | ADDITIVE, ATTACHED, CONTINUOUS, ALIGNED, BEHIND, PMA
20 | }
21 | private Type type;
22 | private boolean newValue;
23 | private String description;
24 |
25 | @Override
26 | public void undo() {
27 | setOption(!newValue);
28 | refreshDisplay();
29 | }
30 |
31 | @Override
32 | public void redo() {
33 | setOption(newValue);
34 | refreshDisplay();
35 | }
36 |
37 | private void setOption(boolean value) {
38 | switch (type) {
39 | case ADDITIVE:
40 | emitter.setAdditive(value);
41 | break;
42 | case ATTACHED:
43 | emitter.setAttached(value);
44 | break;
45 | case CONTINUOUS:
46 | emitter.setContinuous(value);
47 | break;
48 | case ALIGNED:
49 | emitter.setAligned(value);
50 | break;
51 | case BEHIND:
52 | emitter.setBehind(value);
53 | break;
54 | case PMA:
55 | emitter.setPremultipliedAlpha(value);
56 | break;
57 | }
58 | }
59 |
60 | @Override
61 | public void start() {
62 | setOption(newValue);
63 | }
64 |
65 | @Override
66 | public String getDescription() {
67 | return description;
68 | }
69 |
70 | private void refreshDisplay() {
71 | emitterPropertiesPanel.populateScrollTable(null);
72 | particleEffect.reset();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/RangedNumericValueUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.RangedNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
9 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to change the value of a RangedNumericValue.
15 | */
16 | @AllArgsConstructor
17 | public class RangedNumericValueUndoable implements Undoable {
18 | private ParticleEmitter emitter;
19 | public final RangedNumericValue newValue = new RangedNumericValue();
20 | public final RangedNumericValue oldValue = new RangedNumericValue();
21 | private RangedNumericValue value;
22 | private String description;
23 |
24 | @Override
25 | public void undo() {
26 | selectedEmitter = emitter;
27 |
28 | value.set(oldValue);
29 | refreshDisplay();
30 | }
31 |
32 | @Override
33 | public void redo() {
34 | selectedEmitter = emitter;
35 |
36 | value.set(newValue);
37 | refreshDisplay();
38 | }
39 |
40 | @Override
41 | public void start() {
42 | value.set(newValue);
43 | }
44 |
45 | @Override
46 | public String getDescription() {
47 | return description;
48 | }
49 |
50 | private void refreshDisplay() {
51 | effectEmittersPanel.populateEmitters();
52 | emitterPropertiesPanel.populateScrollTable(null);
53 | particleEffect.reset();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/RenameEmitterUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.ray3k.gdxparticleeditor.undo.Undoable;
5 | import lombok.AllArgsConstructor;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
8 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
10 |
11 | /**
12 | * Undoable to change the name of an emitter.
13 | */
14 | @AllArgsConstructor
15 | public class RenameEmitterUndoable implements Undoable {
16 | private ParticleEmitter emitter;
17 | private String oldName;
18 | private String newName;
19 | private String description;
20 |
21 | @Override
22 | public void undo() {
23 | emitter.setName(oldName);
24 | refreshDisplay();
25 | }
26 |
27 | @Override
28 | public void redo() {
29 | emitter.setName(newName);
30 | refreshDisplay();
31 | }
32 |
33 | @Override
34 | public void start() {
35 | emitter.setName(newName);
36 | }
37 |
38 | @Override
39 | public String getDescription() {
40 | return description;
41 | }
42 |
43 | private void refreshDisplay() {
44 | effectEmittersPanel.populateEmitters();
45 | effectEmittersPanel.updateDisableableWidgets();
46 | emitterPropertiesPanel.populateScrollTable(null);
47 | particleEffect.reset();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ScaledNumericValueIndependentUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.IndependentScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
10 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
13 |
14 | /**
15 | * Undoable to change the independent value of a scaled numeric value.
16 | */
17 | @Data
18 | @AllArgsConstructor
19 | public class ScaledNumericValueIndependentUndoable implements Undoable {
20 | private ParticleEmitter emitter;
21 | private IndependentScaledNumericValue value;
22 | private boolean active;
23 | private String description;
24 |
25 | @Override
26 | public void undo() {
27 | selectedEmitter = emitter;
28 |
29 | value.setIndependent(!active);
30 | refreshDisplay();
31 | }
32 |
33 | @Override
34 | public void redo() {
35 | selectedEmitter = emitter;
36 |
37 | value.setIndependent(active);
38 | refreshDisplay();
39 | }
40 |
41 | @Override
42 | public void start() {
43 | value.setIndependent(active);
44 | }
45 |
46 | @Override
47 | public String getDescription() {
48 | return description;
49 | }
50 |
51 | private void refreshDisplay() {
52 | effectEmittersPanel.populateEmitters();
53 | emitterPropertiesPanel.populateScrollTable(null);
54 | particleEffect.reset();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ScaledNumericValueRelativeUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.ScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
10 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
13 |
14 | /**
15 | * Change the relative value of a scaled numeric value.
16 | */
17 | @Data
18 | @AllArgsConstructor
19 | public class ScaledNumericValueRelativeUndoable implements Undoable {
20 | private ParticleEmitter emitter;
21 | private ScaledNumericValue value;
22 | private boolean active;
23 | private String description;
24 |
25 | @Override
26 | public void undo() {
27 | selectedEmitter = emitter;
28 |
29 | value.setRelative(!active);
30 | refreshDisplay();
31 | }
32 |
33 | @Override
34 | public void redo() {
35 | selectedEmitter = emitter;
36 |
37 | value.setRelative(active);
38 | refreshDisplay();
39 | }
40 |
41 | @Override
42 | public void start() {
43 | value.setRelative(active);
44 | }
45 |
46 | @Override
47 | public String getDescription() {
48 | return description;
49 | }
50 |
51 | private void refreshDisplay() {
52 | effectEmittersPanel.populateEmitters();
53 | emitterPropertiesPanel.populateScrollTable(null);
54 | particleEffect.reset();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/ScaledNumericValueUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.ScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
9 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to change the value of a scaled numeric value.
15 | */
16 | @AllArgsConstructor
17 | public class ScaledNumericValueUndoable implements Undoable {
18 | private ParticleEmitter emitter;
19 | public final ScaledNumericValue newValue = new ScaledNumericValue();
20 | public final ScaledNumericValue oldValue = new ScaledNumericValue();
21 | private ScaledNumericValue value;
22 | private String description;
23 |
24 | @Override
25 | public void undo() {
26 | selectedEmitter = emitter;
27 |
28 | value.set(oldValue);
29 | refreshDisplay();
30 | }
31 |
32 | @Override
33 | public void redo() {
34 | selectedEmitter = emitter;
35 |
36 | value.set(newValue);
37 | refreshDisplay();
38 | }
39 |
40 | @Override
41 | public void start() {
42 | value.set(newValue);
43 | }
44 |
45 | @Override
46 | public String getDescription() {
47 | return description;
48 | }
49 |
50 | private void refreshDisplay() {
51 | effectEmittersPanel.populateEmitters();
52 | emitterPropertiesPanel.populateScrollTable(null);
53 | particleEffect.reset();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/SetPropertyUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.ScaledNumericValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 |
8 | import static com.ray3k.gdxparticleeditor.Core.*;
9 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
10 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.ShownProperty;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
12 |
13 | /**
14 | * Undoable to change the active/disabled status of an emitter.
15 | */
16 | @AllArgsConstructor
17 | public class SetPropertyUndoable implements Undoable {
18 | private ParticleEmitter emitter;
19 | private ShownProperty property;
20 | private boolean active;
21 | private String description;
22 |
23 | @Override
24 | public void undo() {
25 | selectedEmitter = emitter;
26 |
27 | activateProperty(!active);
28 |
29 | refreshDisplay(!active);
30 | }
31 |
32 | @Override
33 | public void redo() {
34 | selectedEmitter = emitter;
35 |
36 | activateProperty(active);
37 |
38 | refreshDisplay(active);
39 | }
40 |
41 | @Override
42 | public void start() {
43 | activateProperty(active);
44 |
45 | if (active) emitterPropertiesPanel.populateScrollTable(property);
46 | else emitterPropertiesPanel.removeProperty(property);
47 | }
48 |
49 | public void activateProperty(boolean active) {
50 | switch (property) {
51 | case DELAY:
52 | selectedEmitter.getDelay().setActive(active);
53 | break;
54 | case LIFE_OFFSET:
55 | selectedEmitter.getLifeOffset().setActive(active);
56 | break;
57 | case X_OFFSET:
58 | selectedEmitter.getXOffsetValue().setActive(active);
59 | break;
60 | case Y_OFFSET:
61 | selectedEmitter.getYOffsetValue().setActive(active);
62 | break;
63 | case VELOCITY:
64 | selectedEmitter.getVelocity().setActive(active);
65 | break;
66 | case ANGLE:
67 | selectedEmitter.getAngle().setActive(active);
68 | if (!active) {
69 | var value = new ScaledNumericValue();
70 | value.set(selectedEmitter.getAngle());
71 | defaultAngleMap.put(selectedEmitter, value);
72 |
73 | selectedEmitter.getAngle().setHigh(0);
74 | selectedEmitter.getAngle().setLow(0);
75 | } else {
76 | selectedEmitter.getAngle().set(defaultAngleMap.get(selectedEmitter));
77 | }
78 | break;
79 | case ROTATION:
80 | selectedEmitter.getRotation().setActive(active);
81 | break;
82 | case WIND:
83 | selectedEmitter.getWind().setActive(active);
84 | break;
85 | case GRAVITY:
86 | selectedEmitter.getGravity().setActive(active);
87 | break;
88 | }
89 | }
90 |
91 | @Override
92 | public String getDescription() {
93 | return description;
94 | }
95 |
96 | private void refreshDisplay(boolean active) {
97 | effectEmittersPanel.populateEmitters();
98 | if (active) emitterPropertiesPanel.populateScrollTable(property);
99 | else emitterPropertiesPanel.removeProperty(property);
100 | particleEffect.reset();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/SpawnEdgesUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.SpawnShapeValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
10 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
11 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
13 |
14 | /**
15 | * Undoable to change the edges value of a spawn shape.
16 | */
17 | @Data
18 | @AllArgsConstructor
19 | public class SpawnEdgesUndoable implements Undoable {
20 | private ParticleEmitter emitter;
21 | private SpawnShapeValue value;
22 | private boolean active;
23 | private String description;
24 |
25 | @Override
26 | public void undo() {
27 | selectedEmitter = emitter;
28 |
29 | value.setEdges(!active);
30 | refreshDisplay();
31 | }
32 |
33 | @Override
34 | public void redo() {
35 | selectedEmitter = emitter;
36 |
37 | value.setEdges(active);
38 | refreshDisplay();
39 | }
40 |
41 | @Override
42 | public void start() {
43 | value.setEdges(active);
44 | }
45 |
46 | @Override
47 | public String getDescription() {
48 | return description;
49 | }
50 |
51 | private void refreshDisplay() {
52 | effectEmittersPanel.populateEmitters();
53 | emitterPropertiesPanel.populateScrollTable(null);
54 | particleEffect.reset();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/SpawnSideUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.SpawnEllipseSide;
5 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.SpawnShapeValue;
6 | import com.ray3k.gdxparticleeditor.undo.Undoable;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Data;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
11 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
13 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
14 |
15 | /**
16 | * Undoable to change the side of a spawn shape.
17 | */
18 | @Data
19 | @AllArgsConstructor
20 | public class SpawnSideUndoable implements Undoable {
21 | private ParticleEmitter emitter;
22 | private SpawnShapeValue value;
23 | private SpawnEllipseSide side;
24 | private SpawnEllipseSide oldSide;
25 | private String description;
26 |
27 | @Override
28 | public void undo() {
29 | selectedEmitter = emitter;
30 |
31 | value.setSide(oldSide);
32 | refreshDisplay();
33 | }
34 |
35 | @Override
36 | public void redo() {
37 | selectedEmitter = emitter;
38 |
39 | value.setSide(side);
40 | refreshDisplay();
41 | }
42 |
43 | @Override
44 | public void start() {
45 | value.setSide(side);
46 | }
47 |
48 | @Override
49 | public String getDescription() {
50 | return description;
51 | }
52 |
53 | private void refreshDisplay() {
54 | effectEmittersPanel.populateEmitters();
55 | emitterPropertiesPanel.populateScrollTable(null);
56 | particleEffect.reset();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/SpawnTypeUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.SpawnShapeValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import com.ray3k.gdxparticleeditor.widgets.subpanels.SpawnSubPanel.SpawnType;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Data;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
11 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
13 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
14 |
15 | /**
16 | * Undoable to change the type of a spawn shape.
17 | */
18 | @Data
19 | @AllArgsConstructor
20 | public class SpawnTypeUndoable implements Undoable {
21 | private ParticleEmitter emitter;
22 | private SpawnShapeValue value;
23 | private SpawnType spawnType;
24 | private SpawnType spawnTypeOld;
25 | private String description;
26 |
27 | @Override
28 | public void undo() {
29 | selectedEmitter = emitter;
30 |
31 | value.setShape(spawnTypeOld.spawnShape);
32 | refreshDisplay();
33 | }
34 |
35 | @Override
36 | public void redo() {
37 | selectedEmitter = emitter;
38 |
39 | value.setShape(spawnType.spawnShape);
40 | refreshDisplay();
41 | }
42 |
43 | @Override
44 | public void start() {
45 | value.setShape(spawnType.spawnShape);
46 | }
47 |
48 | public void refreshDisplay() {
49 | effectEmittersPanel.populateEmitters();
50 | emitterPropertiesPanel.populateScrollTable(null);
51 | particleEffect.reset();
52 | }
53 |
54 | @Override
55 | public String getDescription() {
56 | return description;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/undo/undoables/TintUndoable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.undo.undoables;
2 |
3 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter;
4 | import com.badlogic.gdx.graphics.g2d.ParticleEmitter.GradientColorValue;
5 | import com.ray3k.gdxparticleeditor.undo.Undoable;
6 | import com.ray3k.gdxparticleeditor.widgets.ColorGraph;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Data;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.particleEffect;
11 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
12 | import static com.ray3k.gdxparticleeditor.widgets.panels.EffectEmittersPanel.effectEmittersPanel;
13 | import static com.ray3k.gdxparticleeditor.widgets.panels.EmitterPropertiesPanel.emitterPropertiesPanel;
14 |
15 | /**
16 | * Undoable to change the tint of a gradient color value.
17 | */
18 | @Data
19 | @AllArgsConstructor
20 | public class TintUndoable implements Undoable {
21 | private ParticleEmitter emitter;
22 | private GradientColorValue value;
23 | private final GradientColorValue oldValue = new GradientColorValue();
24 | private final GradientColorValue newValue = new GradientColorValue();
25 | private ColorGraph colorGraph;
26 | private String description;
27 |
28 | @Override
29 | public void undo() {
30 | selectedEmitter = emitter;
31 |
32 | value.setTimeline(oldValue.getTimeline());
33 | value.setColors(oldValue.getColors());
34 | refreshDisplay();
35 | }
36 |
37 | @Override
38 | public void redo() {
39 | selectedEmitter = emitter;
40 |
41 | value.setTimeline(newValue.getTimeline());
42 | value.setColors(newValue.getColors());
43 | refreshDisplay();
44 | }
45 |
46 | @Override
47 | public void start() {
48 | value.setTimeline(newValue.getTimeline());
49 | value.setColors(newValue.getColors());
50 | }
51 |
52 | @Override
53 | public String getDescription() {
54 | return description;
55 | }
56 |
57 | private void refreshDisplay() {
58 | effectEmittersPanel.populateEmitters();
59 | emitterPropertiesPanel.populateScrollTable(null);
60 | particleEffect.reset();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/CardGroup.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Actor;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Container;
5 | import com.badlogic.gdx.utils.Array;
6 |
7 | /**
8 | * Widget that allows the user to flip through its children, displaying only one at a time.
9 | */
10 | public class CardGroup extends Container {
11 | public final Array actors = new Array<>();
12 | private int shownIndex = -1;
13 |
14 | public CardGroup(Actor... actors) {
15 | if (actors.length > 0) {
16 | this.actors.addAll(actors);
17 | showIndex(0);
18 | }
19 | fill();
20 | }
21 |
22 | public void showIndex(int index) {
23 | shownIndex = index;
24 | super.setActor(actors.get(index));
25 | }
26 |
27 | public Actor getActor(int index) {
28 | return actors.get(index);
29 | }
30 |
31 | public int getShownIndex() {
32 | return shownIndex;
33 | }
34 |
35 | public Actor getShownActor() {
36 | return actors.get(shownIndex);
37 | }
38 |
39 | public void add(Actor actor) {
40 | actors.add(actor);
41 | if (shownIndex == -1) showIndex(0);
42 | }
43 |
44 | public void remove(Actor actor) {
45 |
46 | }
47 |
48 | @Override @Deprecated
49 | public void setActor(Actor actor) {
50 | super.setActor(actor);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/EditableLabel.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Actor;
4 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
5 | import com.badlogic.gdx.scenes.scene2d.Stage;
6 | import com.badlogic.gdx.scenes.scene2d.Touchable;
7 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
8 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
9 | import com.badlogic.gdx.scenes.scene2d.ui.TextField;
10 | import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
11 | import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
12 | import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
13 | import com.badlogic.gdx.scenes.scene2d.utils.FocusListener;
14 | import lombok.Getter;
15 |
16 | /**
17 | * A label that shows ellipses when its size is decreased below its preferred dimensions. If the user clicks the label,
18 | * the label is converted to a textfield, allowing the text to be modified.
19 | */
20 | public class EditableLabel extends ToggleGroup {
21 | @Getter
22 | private String text;
23 | public Label label;
24 | public TextField textField;
25 | public EditableLabelStyle style;
26 |
27 | public EditableLabel(String text, EditableLabelStyle style) {
28 | this.text = text;
29 | this.style = style;
30 |
31 | label = new Label(text, style.labelStyle);
32 | label.setEllipsis("...");
33 | label.setTouchable(Touchable.enabled);
34 | table1.add(label).grow().minWidth(0);
35 | label.addListener(new ClickListener() {
36 | @Override
37 | public void clicked(InputEvent event, float x, float y) {
38 | swap();
39 | getStage().setKeyboardFocus(textField);
40 | textField.selectAll();
41 | }
42 | });
43 |
44 | textField = new TextField(text, style.textFieldStyle);
45 | table2.add(textField).grow().minWidth(0);
46 | textField.addListener(new ChangeListener() {
47 | @Override
48 | public void changed(ChangeEvent event, Actor actor) {
49 | label.setText(textField.getText());
50 | EditableLabel.this.text = textField.getText();
51 | }
52 | });
53 | textField.addListener(new FocusListener() {
54 | @Override
55 | public void keyboardFocusChanged(FocusEvent event, Actor actor, boolean focused) {
56 | if (focused) textField.selectAll();
57 | else swap();
58 | }
59 | });
60 | }
61 |
62 | @Override
63 | protected void setStage(Stage stage) {
64 | super.setStage(stage);
65 | }
66 |
67 | public void setText(String text) {
68 | this.text = text;
69 | label.setText(text);
70 | textField.setText(text);
71 | }
72 |
73 | public void unfocused() {
74 |
75 | }
76 |
77 | public static class EditableLabelStyle {
78 | public LabelStyle labelStyle;
79 | public TextFieldStyle textFieldStyle;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/NoCaptureKeyboardFocusListener.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Event;
4 | import com.badlogic.gdx.scenes.scene2d.EventListener;
5 |
6 | /**
7 | * A hack to signify that the widget this listener is attached to should not trigger the keyboard focus changed event
8 | * in GDX Particle Editor.
9 | */
10 | public class NoCaptureKeyboardFocusListener implements EventListener {
11 | @Override
12 | public boolean handle(Event event) {
13 | return false;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/Panel.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | /**
8 | * A layout widget comprised of three components: tabTable, topTable, and bodyTable. These are used in conjunction by
9 | * dependent classes to create a visual effect of a tabbed panel.
10 | */
11 | public class Panel extends Table {
12 | public Table tabTable;
13 | public Table topTable;
14 | public Table bodyTable;
15 |
16 | public Panel() {
17 | tabTable = new Table();
18 | add(tabTable);
19 | tabTable.setBackground(skin.getDrawable("panel-tab-10"));
20 |
21 | topTable = new Table();
22 | add(topTable).growX();
23 | topTable.setBackground(skin.getDrawable("panel-top-10"));
24 |
25 | row();
26 | bodyTable = new Table();
27 | add(bodyTable).grow().colspan(2);
28 | bodyTable.setBackground(skin.getDrawable("panel-body-10"));
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/Toast.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.math.Interpolation;
4 | import com.badlogic.gdx.scenes.scene2d.Stage;
5 | import com.badlogic.gdx.scenes.scene2d.ui.Skin;
6 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
7 | import com.ray3k.stripe.PopTable;
8 |
9 | import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;
10 |
11 | public class Toast extends PopTable {
12 | private float transitionTime;
13 | private float showTime;
14 |
15 | public Toast(float transitionTime, float showTime) {
16 | this.transitionTime = transitionTime;
17 | this.showTime = showTime;
18 | }
19 |
20 | public Toast(Skin skin, float transitionTime, float showTime) {
21 | super(skin);
22 | this.transitionTime = transitionTime;
23 | this.showTime = showTime;
24 | }
25 |
26 | public Toast(Skin skin, String style, float transitionTime, float showTime) {
27 | super(skin, style);
28 | this.transitionTime = transitionTime;
29 | this.showTime = showTime;
30 | }
31 |
32 | public Toast(WindowStyle style, float transitionTime, float showTime) {
33 | super(style);
34 | this.transitionTime = transitionTime;
35 | this.showTime = showTime;
36 | }
37 |
38 | public Toast(PopTableStyle style, float transitionTime, float showTime) {
39 | super(style);
40 | this.transitionTime = transitionTime;
41 | this.showTime = showTime;
42 | }
43 |
44 | @Override
45 | public void show(Stage stage) {
46 | super.show(stage, null);
47 | setKeepSizedWithinStage(false);
48 | getParentGroup().setColor(1, 1, 1, 1);
49 | addAction(sequence(
50 | moveTo(getStage().getWidth() / 2f - getWidth() / 2f, -getHeight()),
51 | moveTo(getStage().getWidth() / 2f - getWidth() / 2f, 0, transitionTime, Interpolation.exp5Out),
52 | delay(showTime),
53 | run(this::hide)
54 | ));
55 | }
56 |
57 | @Override
58 | public void hide() {
59 | addAction(sequence(
60 | moveTo(getStage().getWidth() / 2f - getWidth() / 2f, -getHeight(), transitionTime, Interpolation.exp5In),
61 | run(() -> super.hide(null))
62 | ));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/ToggleGroup.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Container;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
5 |
6 | /**
7 | * A layout widget that can be programmatically changed to display one of two tables. This is useful in user interfaces
8 | * that need to display alternate layouts depending on certain criteria.
9 | */
10 | public class ToggleGroup extends Container {
11 | public Table table1 = new Table();
12 | public Table table2 = new Table();
13 | public boolean showingTable1;
14 |
15 | public ToggleGroup() {
16 | showTable1();
17 | fill();
18 | }
19 |
20 | public void showTable1() {
21 | setActor(table1);
22 | showingTable1 = true;
23 | }
24 |
25 | public void showTable2() {
26 | setActor(table2);
27 | showingTable1 = false;
28 | }
29 |
30 | public void swap() {
31 | if (showingTable1) showTable2();
32 | else showTable1();
33 | }
34 |
35 | @Override @Deprecated
36 | public void setActor(Table table) {
37 | super.setActor(table);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/WelcomeCard.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Button;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Image;
5 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
6 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
7 | import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
8 |
9 | import static com.ray3k.gdxparticleeditor.Core.skin;
10 |
11 | /**
12 | * A clickable button to be used with the welcome screen. It consists of a title, an image, description, and a child
13 | * TextButton.
14 | */
15 | public class WelcomeCard extends Button {
16 | public WelcomeCard(String title, String subtitle, Drawable drawable, String buttonText) {
17 | super(skin, "card");
18 |
19 | top().left();
20 |
21 | defaults().space(15);
22 | var label = new Label(title, skin, "bold");
23 | add(label).left().expandX();
24 |
25 | row();
26 | var image = new Image(drawable);
27 | add(image).size(240, 190);
28 |
29 | row();
30 | label = new Label(subtitle, skin);
31 | add(label);
32 |
33 | row();
34 | var textButton = new TextButton(buttonText, skin, "highlighted-card");
35 | add(textButton).expandX().right();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/panels/StartPanel.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.panels;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.math.Vector2;
5 | import com.badlogic.gdx.scenes.scene2d.Touchable;
6 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
7 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
8 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
9 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
10 | import com.ray3k.gdxparticleeditor.widgets.Panel;
11 |
12 | import static com.ray3k.gdxparticleeditor.Core.skin;
13 | import static com.ray3k.gdxparticleeditor.Listeners.*;
14 |
15 | /**
16 | * An introductory screen used exclusively in Wizard mode to help introduce users to GDX Particle Editor.
17 | */
18 | public class StartPanel extends Panel {
19 | private Table scrollTable;
20 | public static StartPanel summaryPanel;
21 | private ScrollPane scrollPane;
22 | private static final Vector2 temp = new Vector2();
23 |
24 | public StartPanel() {
25 | summaryPanel = this;
26 | setTouchable(Touchable.enabled);
27 |
28 | var label = new Label("Start", skin, "header");
29 | tabTable.add(label);
30 |
31 | bodyTable.defaults().space(5);
32 | scrollTable = new Table();
33 | scrollPane = new ScrollPane(scrollTable, skin, "emitter-properties");
34 | scrollPane.setFlickScroll(false);
35 | bodyTable.add(scrollPane).grow();
36 | addScrollFocusListener(scrollPane);
37 |
38 | populateScrollTable();
39 | }
40 |
41 | public void populateScrollTable() {
42 | scrollTable.clearChildren(true);
43 | scrollTable.defaults().space(10);
44 |
45 | var label = new Label("Welcome!", skin, "bold");
46 | scrollTable.add(label);
47 |
48 | scrollTable.row();
49 | label = new Label("GDX Particle Editor allows you to create particle effects for your libGDX games.", skin);
50 | scrollTable.add(label);
51 |
52 | scrollTable.row();
53 | var table = new Table();
54 | table.columnDefaults(0).right();
55 | table.columnDefaults(1).left();
56 | scrollTable.add(table).padTop(10);
57 |
58 | var titleLabel = new Label("Effect Emitters:", skin, "header");
59 | titleLabel.setColor(skin.getColor("selection"));
60 | table.add(titleLabel);
61 |
62 | label = new Label(" load and create the emitters that comprise your particle effect", skin);
63 | table.add(label);
64 |
65 | table.row();
66 | titleLabel = new Label("Emitter Properties:", skin, "header");
67 | titleLabel.setColor(skin.getColor("selection"));
68 | table.add(titleLabel);
69 |
70 | label = new Label(" edit the behavior and appearance of the selected emitter", skin);
71 | table.add(label);
72 |
73 | table.row();
74 | titleLabel = new Label("Summary:", skin, "header");
75 | titleLabel.setColor(skin.getColor("selection"));
76 | table.add(titleLabel);
77 |
78 | label = new Label(" save your particle effect to a file that can be loaded in libGDX", skin);
79 | table.add(label);
80 |
81 | scrollTable.row();
82 | label = new Label("Learn", skin, "bold");
83 | scrollTable.add(label).padTop(20);
84 |
85 | scrollTable.row();
86 | table = new Table();
87 | table.defaults().space(10);
88 | scrollTable.add(table);
89 |
90 | var textButton = new TextButton("GitHub", skin);
91 | table.add(textButton);
92 | addHandListener(textButton);
93 | onChange(textButton, () -> {
94 | Gdx.net.openURI("https://github.com/libgdx/gdx-particle-editor");
95 | });
96 |
97 | textButton = new TextButton("YouTube", skin);
98 | table.add(textButton);
99 | addHandListener(textButton);
100 | onChange(textButton, () -> {
101 |
102 | });
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/panels/SummaryPanel.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.panels;
2 |
3 | import com.badlogic.gdx.math.Vector2;
4 | import com.badlogic.gdx.scenes.scene2d.Touchable;
5 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
6 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
7 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
8 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
9 | import com.ray3k.gdxparticleeditor.widgets.Panel;
10 |
11 | import static com.ray3k.gdxparticleeditor.Core.*;
12 | import static com.ray3k.gdxparticleeditor.Listeners.*;
13 |
14 | /**
15 | * A summary screen used exclusively in wizard mode that displays some emitter statistics and gives the user an option
16 | * to save.
17 | */
18 | public class SummaryPanel extends Panel {
19 | private Table scrollTable;
20 | public static SummaryPanel summaryPanel;
21 | private ScrollPane scrollPane;
22 | private static final Vector2 temp = new Vector2();
23 |
24 | public SummaryPanel() {
25 | summaryPanel = this;
26 | setTouchable(Touchable.enabled);
27 |
28 | var label = new Label("Summary", skin, "header");
29 | tabTable.add(label);
30 |
31 | bodyTable.defaults().space(5);
32 | scrollTable = new Table();
33 | scrollPane = new ScrollPane(scrollTable, skin, "emitter-properties");
34 | scrollPane.setFlickScroll(false);
35 | bodyTable.add(scrollPane).grow();
36 | addScrollFocusListener(scrollPane);
37 |
38 | populateScrollTable();
39 | }
40 |
41 | public void populateScrollTable() {
42 | scrollTable.clearChildren(true);
43 | scrollTable.defaults().space(10);
44 |
45 | var label = new Label("Congratulations! You have created a particle effect. It looks great!", skin);
46 | scrollTable.add(label);
47 |
48 | scrollTable.row();
49 | var table = new Table();
50 | scrollTable.add(table);
51 |
52 | table.defaults().spaceRight(10).uniformX();
53 | table.columnDefaults(0).right();
54 | table.columnDefaults(1).left();
55 | label = new Label("Emitters:", skin, "header");
56 | label.setColor(skin.getColor("selection"));
57 | table.add(label);
58 |
59 | label = new Label(Integer.toString(activeEmitters.size), skin);
60 | table.add(label);
61 |
62 | table.row();
63 | label = new Label("Images:", skin, "header");
64 | label.setColor(skin.getColor("selection"));
65 | table.add(label);
66 |
67 | label = new Label(Integer.toString(fileHandles.size), skin);
68 | table.add(label);
69 |
70 | table.row();
71 | label = new Label("Max particle count:", skin, "header");
72 | label.setColor(skin.getColor("selection"));
73 | table.add(label);
74 |
75 | label = new Label(Integer.toString(maxParticleCount), skin);
76 | table.add(label);
77 |
78 | scrollTable.row();
79 | label = new Label("Save Particle Effect?", skin, "bold");
80 | scrollTable.add(label).padTop(20);
81 |
82 | scrollTable.row();
83 | var textButton = new TextButton("Save", skin);
84 | scrollTable.add(textButton);
85 | addHandListener(textButton);
86 | onChange(textButton, saveRunnable);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/poptables/PopConfirmClose.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.poptables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.Input.Keys;
5 | import com.badlogic.gdx.InputProcessor;
6 | import com.badlogic.gdx.scenes.scene2d.Event;
7 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
8 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
9 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
10 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
11 | import com.badlogic.gdx.utils.Align;
12 | import com.ray3k.gdxparticleeditor.Listeners;
13 | import com.ray3k.gdxparticleeditor.runnables.SaveAsRunnable;
14 | import com.ray3k.gdxparticleeditor.runnables.SaveRunnable;
15 | import com.ray3k.stripe.PopTable;
16 |
17 | import static com.ray3k.gdxparticleeditor.Core.foregroundStage;
18 | import static com.ray3k.gdxparticleeditor.Core.skin;
19 | import static com.ray3k.gdxparticleeditor.Listeners.*;
20 | import static com.ray3k.gdxparticleeditor.Listeners.addHandListener;
21 | import static com.ray3k.gdxparticleeditor.Listeners.onChange;
22 |
23 | /**
24 | * PopTable used to display errors during runtime that can be recovered from. These are typically file errors when
25 | * saving or opening particles and images. A link to the log directory enables users to retrieve the crash log file
26 | * through their OS file explorer.
27 | */
28 | public class PopConfirmClose extends PopTable {
29 | private final InputProcessor previousInputProcessor;
30 |
31 | public PopConfirmClose() {
32 | super(skin.get(WindowStyle.class));
33 |
34 | setHideOnUnfocus(true);
35 | key(Keys.ESCAPE, this::hide);
36 | key(Keys.ENTER, this::save);
37 | key(Keys.NUMPAD_ENTER, this::save);
38 |
39 | previousInputProcessor = Gdx.input.getInputProcessor();
40 | Gdx.input.setInputProcessor(foregroundStage);
41 |
42 | addListener(new TableShowHideListener() {
43 | @Override
44 | public void tableShown(Event event) {
45 | hideAllTooltips();
46 | }
47 |
48 | @Override
49 | public void tableHidden(Event event) {
50 | if (Gdx.input.getInputProcessor() == foregroundStage) Gdx.input.setInputProcessor(previousInputProcessor);
51 | }
52 | });
53 | populate();
54 | }
55 |
56 | private void populate() {
57 | clearChildren();
58 | pad(20);
59 | defaults().space(10);
60 |
61 | var label = new Label("Save Changes?", skin, "bold");
62 | add(label);
63 |
64 | row();
65 | label = new Label("Do you want to save your changes before you quit?", skin);
66 | label.setWrap(true);
67 | label.setAlignment(Align.center);
68 | add(label).growX();
69 |
70 | row();
71 | var table = new Table();
72 | table.defaults().uniformX().fillX().space(10);
73 | add(table);
74 |
75 | var textButton = new TextButton("Save changes", skin, "highlighted");
76 | table.add(textButton);
77 | addHandListener(textButton);
78 | onChange(textButton, () -> {
79 | save();
80 | });
81 |
82 | textButton = new TextButton("Close without saving", skin, "highlighted-red");
83 | table.add(textButton);
84 | addHandListener(textButton);
85 | onChange(textButton, Gdx.app::exit);
86 |
87 | textButton = new TextButton("Cancel", skin);
88 | table.add(textButton);
89 | addHandListener(textButton);
90 | onChange(textButton, () -> {
91 | hide();
92 | });
93 | }
94 |
95 | private void save() {
96 | hide();
97 |
98 | var saveFirstRunnable = new SaveRunnable();
99 | var saveAsFirstRunnable = new SaveAsRunnable();
100 |
101 | saveFirstRunnable.setSaveAsRunnable(saveAsFirstRunnable);
102 | saveAsFirstRunnable.setSaveRunnable(saveFirstRunnable);
103 | saveFirstRunnable.setOnCompletionRunnable(() -> Gdx.app.exit());
104 | saveFirstRunnable.run();
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/poptables/PopConfirmLoad.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.poptables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.Input.Keys;
5 | import com.badlogic.gdx.InputProcessor;
6 | import com.badlogic.gdx.scenes.scene2d.Event;
7 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
8 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
9 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
10 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
11 | import com.badlogic.gdx.utils.Align;
12 | import com.ray3k.gdxparticleeditor.Listeners;
13 | import com.ray3k.gdxparticleeditor.Utils;
14 | import com.ray3k.stripe.PopTable;
15 |
16 | import static com.ray3k.gdxparticleeditor.Core.foregroundStage;
17 | import static com.ray3k.gdxparticleeditor.Core.skin;
18 | import static com.ray3k.gdxparticleeditor.Listeners.*;
19 | import static com.ray3k.gdxparticleeditor.Listeners.addHandListener;
20 | import static com.ray3k.gdxparticleeditor.Listeners.onChange;
21 |
22 | /**
23 | * PopTable used to display errors during runtime that can be recovered from. These are typically file errors when
24 | * saving or opening particles and images. A link to the log directory enables users to retrieve the crash log file
25 | * through their OS file explorer.
26 | */
27 | public class PopConfirmLoad extends PopTable {
28 | private final InputProcessor previousInputProcessor;
29 | private Runnable runnableSave;
30 | private Runnable runnableDiscard;
31 |
32 | public PopConfirmLoad(Runnable runnableSave, Runnable runnableDiscard) {
33 | super(skin.get(WindowStyle.class));
34 |
35 | setHideOnUnfocus(true);
36 | key(Keys.ESCAPE, this::hide);
37 | key(Keys.ENTER, this::save);
38 | key(Keys.NUMPAD_ENTER, this::save);
39 |
40 | this.runnableSave = runnableSave;
41 | this.runnableDiscard = runnableDiscard;
42 |
43 | addListener(new TableShowHideListener() {
44 | @Override
45 | public void tableShown(Event event) {
46 | hideAllTooltips();
47 | }
48 |
49 | @Override
50 | public void tableHidden(Event event) {
51 | if (Gdx.input.getInputProcessor() == foregroundStage) Gdx.input.setInputProcessor(previousInputProcessor);
52 | }
53 | });
54 |
55 | previousInputProcessor = Gdx.input.getInputProcessor();
56 | Gdx.input.setInputProcessor(foregroundStage);
57 | populate();
58 | }
59 |
60 | private void populate() {
61 | clearChildren();
62 | pad(20);
63 | defaults().space(10);
64 |
65 | var label = new Label("Save Changes?", skin, "bold");
66 | add(label);
67 |
68 | row();
69 | label = new Label("Do you want to save your changes before loading the particle effect?", skin);
70 | label.setWrap(true);
71 | label.setAlignment(Align.center);
72 | add(label).growX();
73 |
74 | row();
75 | var table = new Table();
76 | table.defaults().uniformX().fillX().space(10);
77 | add(table);
78 |
79 | var textButton = new TextButton("Save changes", skin, "highlighted");
80 | table.add(textButton);
81 | addHandListener(textButton);
82 | onChange(textButton, () -> {
83 | save();
84 | });
85 |
86 | textButton = new TextButton("Discard changes", skin, "highlighted-red");
87 | table.add(textButton);
88 | addHandListener(textButton);
89 | onChange(textButton, () -> {
90 | hide();
91 | Gdx.input.setInputProcessor(previousInputProcessor);
92 | runnableDiscard.run();
93 | });
94 |
95 | textButton = new TextButton("Cancel", skin);
96 | table.add(textButton);
97 | addHandListener(textButton);
98 | onChange(textButton, () -> {
99 | hide();
100 | Gdx.input.setInputProcessor(previousInputProcessor);
101 | });
102 | }
103 |
104 | private void save() {
105 | hide();
106 | Gdx.input.setInputProcessor(previousInputProcessor);
107 | runnableSave.run();
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/poptables/PopError.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.poptables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.Input.Keys;
5 | import com.badlogic.gdx.InputProcessor;
6 | import com.badlogic.gdx.graphics.Color;
7 | import com.badlogic.gdx.scenes.scene2d.Action;
8 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
9 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
10 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
11 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
12 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
13 | import com.ray3k.gdxparticleeditor.Listeners;
14 | import com.ray3k.gdxparticleeditor.Utils;
15 | import com.ray3k.stripe.PopTable;
16 |
17 | import java.io.IOException;
18 |
19 | import static com.ray3k.gdxparticleeditor.Core.foregroundStage;
20 | import static com.ray3k.gdxparticleeditor.Core.skin;
21 | import static com.ray3k.gdxparticleeditor.Settings.logFile;
22 |
23 | /**
24 | * PopTable used to display errors during runtime that can be recovered from. These are typically file errors when
25 | * saving or opening particles and images. A link to the log directory enables users to retrieve the crash log file
26 | * through their OS file explorer.
27 | */
28 | public class PopError extends PopTable {
29 | private String message;
30 | private String error;
31 | private final InputProcessor previousInputProcessor;
32 |
33 | public PopError(String message, String error) {
34 | super(skin.get(WindowStyle.class));
35 |
36 | setHideOnUnfocus(true);
37 | key(Keys.ESCAPE, this::hide);
38 |
39 | this.message = message;
40 | this.error = error;
41 |
42 | populate();
43 | previousInputProcessor = Gdx.input.getInputProcessor();
44 | Gdx.input.setInputProcessor(foregroundStage);
45 | }
46 |
47 | @Override
48 | public void hide(Action action) {
49 | super.hide(action);
50 | if (Gdx.input.getInputProcessor() == foregroundStage) Gdx.input.setInputProcessor(previousInputProcessor);
51 | }
52 |
53 | private void populate() {
54 | clearChildren();
55 | pad(20);
56 | defaults().space(10);
57 |
58 | var label = new Label("GDX Particle Editor encountered an error:", skin, "bold");
59 | add(label);
60 |
61 | row();
62 | label = new Label(message, skin);
63 | label.setWrap(true);
64 | add(label).growX();
65 |
66 | row();
67 | var scrollPane = new ScrollPane(null, skin);
68 | add(scrollPane).grow();
69 |
70 | label = new Label(error, skin);
71 | label.setColor(Color.RED);
72 | scrollPane.setActor(label);
73 |
74 | row();
75 | var table = new Table();
76 | table.defaults().uniformX().fillX().space(10);
77 | add(table);
78 |
79 | var textButton = new TextButton("Close", skin);
80 | table.add(textButton);
81 | Listeners.addHandListener(textButton);
82 | Listeners.onChange(textButton, () -> {
83 | hide();
84 | });
85 |
86 | textButton = new TextButton("Open log", skin);
87 | table.add(textButton);
88 | Listeners.addHandListener(textButton);
89 | Listeners.onChange(textButton, () -> {
90 | try {
91 | Utils.openFileExplorer(logFile);
92 | } catch (IOException e) {
93 | e.printStackTrace();
94 | }
95 |
96 | hide();
97 | });
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/poptables/PopImageError.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.poptables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.Input.Keys;
5 | import com.badlogic.gdx.InputProcessor;
6 | import com.badlogic.gdx.files.FileHandle;
7 | import com.badlogic.gdx.graphics.Color;
8 | import com.badlogic.gdx.graphics.Cursor.SystemCursor;
9 | import com.badlogic.gdx.scenes.scene2d.Action;
10 | import com.badlogic.gdx.scenes.scene2d.Stage;
11 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
12 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
13 | import com.badlogic.gdx.scenes.scene2d.ui.Table;
14 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
15 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
16 | import com.ray3k.gdxparticleeditor.Core;
17 | import com.ray3k.gdxparticleeditor.Listeners;
18 | import com.ray3k.gdxparticleeditor.Utils;
19 | import com.ray3k.stripe.PopTable;
20 |
21 | import java.io.IOException;
22 |
23 | import static com.ray3k.gdxparticleeditor.Core.foregroundStage;
24 | import static com.ray3k.gdxparticleeditor.Core.skin;
25 | import static com.ray3k.gdxparticleeditor.Settings.logFile;
26 |
27 | /**
28 | * PopTable used to display errors during runtime that can be recovered from. These are typically file errors when
29 | * saving or opening particles and images. A link to the log directory enables users to retrieve the crash log file
30 | * through their OS file explorer.
31 | */
32 | public class PopImageError extends PopTable {
33 | private String message;
34 | private String error;
35 | private boolean merge;
36 | private final InputProcessor previousInputProcessor;
37 |
38 | public PopImageError(String message, String error, FileHandle particleFile, boolean merge) {
39 | super(skin.get(WindowStyle.class));
40 |
41 | setHideOnUnfocus(true);
42 | key(Keys.ESCAPE, this::hide);
43 |
44 | this.message = message;
45 | this.error = error;
46 | this.merge = merge;
47 |
48 | populate(particleFile);
49 | previousInputProcessor = Gdx.input.getInputProcessor();
50 | Gdx.input.setInputProcessor(foregroundStage);
51 | }
52 |
53 | @Override
54 | public void hide(Action action) {
55 | super.hide(action);
56 | if (Gdx.input.getInputProcessor() == foregroundStage) Gdx.input.setInputProcessor(previousInputProcessor);
57 | }
58 |
59 | private void populate(FileHandle particleFile) {
60 | clearChildren();
61 | pad(20);
62 | defaults().space(10);
63 |
64 | var label = new Label("GDX Particle Editor encountered an error:", skin, "bold");
65 | add(label);
66 |
67 | row();
68 | label = new Label(message, skin);
69 | label.setWrap(true);
70 | add(label).growX();
71 |
72 | row();
73 | var scrollPane = new ScrollPane(null, skin);
74 | add(scrollPane).grow();
75 |
76 | label = new Label(error, skin);
77 | label.setColor(Color.RED);
78 | scrollPane.setActor(label);
79 |
80 | row();
81 | var table = new Table();
82 | table.defaults().uniformX().fillX().space(10);
83 | add(table);
84 |
85 | var textButton = new TextButton("Locate images...", skin);
86 | table.add(textButton);
87 | Listeners.addHandListener(textButton);
88 | Listeners.onChange(textButton, () -> {
89 | hide();
90 | Gdx.graphics.setSystemCursor(SystemCursor.Arrow);
91 |
92 | var pop = new PopLocateImages(particleFile, merge);
93 | pop.show(foregroundStage);
94 | });
95 |
96 | textButton = new TextButton("Close", skin);
97 | table.add(textButton);
98 | Listeners.addHandListener(textButton);
99 | Listeners.onChange(textButton, () -> {
100 | hide();
101 | });
102 |
103 | textButton = new TextButton("Open log", skin);
104 | table.add(textButton);
105 | Listeners.addHandListener(textButton);
106 | Listeners.onChange(textButton, () -> {
107 | try {
108 | Utils.openFileExplorer(logFile);
109 | } catch (IOException e) {
110 | e.printStackTrace();
111 | }
112 |
113 | hide();
114 | });
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPcolorGraphStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.gdxparticleeditor.widgets.ColorGraph.ColorGraphStyle;
4 | import com.ray3k.tenpatch.TenPatchDrawable;
5 |
6 | import static com.ray3k.gdxparticleeditor.Core.skin;
7 |
8 | public class PPcolorGraphStyle extends ColorGraphStyle {
9 | public PPcolorGraphStyle() {
10 | background = skin.getDrawable("colorbar-bg-10");
11 | nodeStartUp = skin.getDrawable("colorbar-left-bg");
12 | nodeStartOver = null;
13 | nodeStartDown = null;
14 | nodeStartFill = skin.getDrawable("colorbar-left-fill");
15 | nodeUp = skin.getDrawable("colorbar-knob-bg");
16 | nodeOver = null;
17 | nodeDown = null;
18 | nodeFill = skin.getDrawable("colorbar-knob-fill");
19 | nodeEndUp = skin.getDrawable("colorbar-right-bg");
20 | nodeEndOver = null;
21 | nodeEndDown = null;
22 | nodeEndFill = skin.getDrawable("colorbar-right-fill");
23 | white = skin.get("colorbar-white-10", TenPatchDrawable.class);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPcolorPickerStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.ImageButton.ImageButtonStyle;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
5 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane.ScrollPaneStyle;
6 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
7 | import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
8 | import com.ray3k.stripe.PopColorPicker.PopColorPickerStyle;
9 |
10 | import static com.ray3k.gdxparticleeditor.Core.skin;
11 |
12 | public class PPcolorPickerStyle extends PopColorPickerStyle {
13 | public PPcolorPickerStyle() {
14 | background = skin.getDrawable("cp-background-10");
15 | stageBackground = skin.getDrawable("stage-background");
16 | titleBarBackground = skin.getDrawable("cp-header-10");
17 | labelStyle = skin.get(LabelStyle.class);
18 | textButtonStyle = skin.get(TextButtonStyle.class);
19 | fileTextButtonStyle = skin.get("cp-file", TextButtonStyle.class);
20 | scrollPaneStyle = skin.get(ScrollPaneStyle.class);
21 | colorSwatch = skin.getDrawable("cp-color-swatch");
22 | colorSwatchNew = skin.getDrawable("cp-color-swatch-new");
23 | colorSwatchPopBackground = skin.getDrawable("cp-color-swatch-pop-background-10");
24 | previewSwatchBackground = skin.getDrawable("cp-swatch");
25 | previewSwatchOld = skin.getDrawable("cp-swatch-old");
26 | previewSwatchNew = skin.getDrawable("cp-swatch-new");
27 | previewSwatchSingleBackground = skin.getDrawable("cp-swatch-null");
28 | previewSwatchSingle = skin.getDrawable("cp-swatch-new-null");
29 | textFieldStyle = skin.get(TextFieldStyle.class);
30 | hexTextFieldStyle = skin.get("cp", TextFieldStyle.class);
31 | colorSwatchPopPreview = skin.getDrawable("cp-color-swatch-pop-preview");
32 | colorSliderBackground = skin.getDrawable("cp-slider-background-10");
33 | colorSliderKnobHorizontal = skin.getDrawable("cp-slider-knob-horizontal");
34 | colorSliderKnobVertical = skin.getDrawable("cp-slider-knob-vertical");
35 | colorKnobCircleBackground = skin.getDrawable("cp-color-knob-circle-background");
36 | colorKnobCircleForeground = skin.getDrawable("cp-color-circle-knob-foreground");
37 | radioButtonStyle = skin.get("cp-radio", ImageButtonStyle.class);
38 | increaseButtonStyle = skin.get("cp-up", ImageButtonStyle.class);
39 | decreaseButtonStyle = skin.get("cp-down", ImageButtonStyle.class);
40 | checkerBackground = skin.getDrawable("cp-checker-10");
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPdraggableListStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.stripe.DraggableList.DraggableListStyle;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | public class PPdraggableListStyle extends DraggableListStyle {
8 | public PPdraggableListStyle() {
9 | dividerUp = skin.getDrawable("draggable-list-divider-10");
10 | dividerOver = skin.getDrawable("draggable-list-divider-over-10");
11 | transparencyOnDrag = .25f;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPdraggableTextListNoBGStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.stripe.DraggableTextList.DraggableTextListStyle;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | public class PPdraggableTextListNoBGStyle extends DraggableTextListStyle {
8 | public PPdraggableTextListNoBGStyle() {
9 | dividerUp = skin.getDrawable("draggable-list-divider-10");
10 | dividerOver = skin.getDrawable("draggable-list-divider-over-10");
11 | validBackgroundUp = skin.getDrawable("draggable-list-drag-background-10");
12 | dragBackgroundUp = skin.getDrawable("draggable-list-drag-remove-10");
13 | transparencyOnDrag = .25f;
14 |
15 | font = skin.getFont("font-black");
16 | textBackgroundUp = skin.getDrawable("list-selection-invisible");
17 | textBackgroundDown = skin.getDrawable("list-selection-invisible");
18 | textBackgroundOver = skin.getDrawable("list-over-10");
19 | textBackgroundChecked = skin.getDrawable("list-selection-10");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPdraggableTextListStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.stripe.DraggableTextList.DraggableTextListStyle;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | public class PPdraggableTextListStyle extends DraggableTextListStyle {
8 | public PPdraggableTextListStyle() {
9 | dividerUp = skin.getDrawable("draggable-list-divider-10");
10 | dividerOver = skin.getDrawable("draggable-list-divider-over-10");
11 | background = skin.getDrawable("draggable-list-10");
12 | validBackgroundUp = skin.getDrawable("draggable-list-drag-background-10");
13 | dragBackgroundUp = skin.getDrawable("draggable-list-drag-remove-10");
14 | transparencyOnDrag = .25f;
15 |
16 | font = skin.getFont("font-black");
17 | textBackgroundUp = skin.getDrawable("list-selection-invisible");
18 | textBackgroundDown = skin.getDrawable("list-selection-invisible");
19 | textBackgroundOver = skin.getDrawable("list-selection-10");
20 | textBackgroundChecked = null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPeditableLabelStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
4 | import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
5 | import com.ray3k.gdxparticleeditor.widgets.EditableLabel.EditableLabelStyle;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.skin;
8 |
9 | public class PPeditableLabelStyle extends EditableLabelStyle {
10 | public PPeditableLabelStyle() {
11 | labelStyle = skin.get(LabelStyle.class);
12 | textFieldStyle = skin.get("editable-label-selection", TextFieldStyle.class);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPinfSliderStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.gdxparticleeditor.widgets.InfSlider.InfSliderStyle;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | public class PPinfSliderStyle extends InfSliderStyle {
8 | public PPinfSliderStyle() {
9 | background = skin.getDrawable("slider-bg-10");
10 | knobUp = skin.getDrawable("slider-knob");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPlineGraphBigStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.graphics.Color;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
5 | import com.ray3k.gdxparticleeditor.widgets.LineGraph.LineGraphStyle;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.skin;
8 |
9 | public class PPlineGraphBigStyle extends LineGraphStyle {
10 | public PPlineGraphBigStyle() {
11 | background = skin.getDrawable("graph-big-bg-10");
12 | backgroundLabelStyle = skin.get("graph", LabelStyle.class);
13 | knobLabelStyle = skin.get("graph-node", LabelStyle.class);
14 | nodeUp = skin.getDrawable("graph-node-up");
15 | nodeDown = skin.getDrawable("graph-node-over");
16 | nodeOver = skin.getDrawable("graph-node-over");
17 | lineColor = Color.valueOf("0074ff");
18 | lineWidth = 2;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPlineGraphStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.graphics.Color;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
5 | import com.ray3k.gdxparticleeditor.widgets.LineGraph.LineGraphStyle;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.skin;
8 |
9 | public class PPlineGraphStyle extends LineGraphStyle {
10 | public PPlineGraphStyle() {
11 | background = skin.getDrawable("graph-bg-10");
12 | backgroundLabelStyle = skin.get("graph", LabelStyle.class);
13 | nodeUp = skin.getDrawable("graph-node-up");
14 | nodeDown = skin.getDrawable("graph-node-over");
15 | nodeOver = skin.getDrawable("graph-node-over");
16 | lineColor = Color.valueOf("0074ff");
17 | lineWidth = 2;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPresizeWidgetStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.ray3k.stripe.ResizeWidget.ResizeWidgetStyle;
4 |
5 | import static com.ray3k.gdxparticleeditor.Core.skin;
6 |
7 | public class PPresizeWidgetStyle extends ResizeWidgetStyle {
8 | public PPresizeWidgetStyle() {
9 | background = skin.getDrawable("resize-background-10");
10 | handle = skin.getDrawable("resize-knob-up");
11 | handleOver = skin.getDrawable("resize-knob-over");
12 | minorHandle = skin.getDrawable("resize-knob-up");
13 | minorHandleOver = skin.getDrawable("resize-knob-over");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/PPspinnerStyle.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Button.ButtonStyle;
4 | import com.badlogic.gdx.scenes.scene2d.ui.TextField.TextFieldStyle;
5 | import com.ray3k.stripe.Spinner.SpinnerStyle;
6 |
7 | import static com.ray3k.gdxparticleeditor.Core.skin;
8 |
9 | public class PPspinnerStyle extends SpinnerStyle {
10 | public PPspinnerStyle() {
11 | buttonPlusStyle = skin.get("spinner-top", ButtonStyle.class);
12 | buttonMinusStyle = skin.get("spinner-bottom", ButtonStyle.class);
13 | textFieldStyle = skin.get("spinner", TextFieldStyle.class);;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/styles/Styles.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.styles;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.ui.Window.WindowStyle;
4 | import com.ray3k.gdxparticleeditor.widgets.ColorGraph.ColorGraphStyle;
5 | import com.ray3k.gdxparticleeditor.widgets.EditableLabel.EditableLabelStyle;
6 | import com.ray3k.gdxparticleeditor.widgets.InfSlider.InfSliderStyle;
7 | import com.ray3k.gdxparticleeditor.widgets.LineGraph.LineGraphStyle;
8 | import com.ray3k.stripe.DraggableList.DraggableListStyle;
9 | import com.ray3k.stripe.DraggableTextList.DraggableTextListStyle;
10 | import com.ray3k.stripe.PopColorPicker.PopColorPickerStyle;
11 | import com.ray3k.stripe.PopTable.PopTableStyle;
12 | import com.ray3k.stripe.ResizeWidget.ResizeWidgetStyle;
13 | import com.ray3k.stripe.Spinner.SpinnerStyle;
14 |
15 | import static com.ray3k.gdxparticleeditor.Core.skin;
16 |
17 | /**
18 | * Collection of styles for custom widgets that are not provided in the skin JSON.
19 | */
20 | public class Styles {
21 | public static LineGraphStyle lineGraphStyle;
22 | public static LineGraphStyle lineGraphBigStyle;
23 | public static ColorGraphStyle colorGraphStyle;
24 | public static SpinnerStyle spinnerStyle;
25 | public static ResizeWidgetStyle resizeWidgetStyle;
26 | public static DraggableListStyle draggableListStyle;
27 | public static DraggableTextListStyle draggableTextListStyle;
28 | public static DraggableTextListStyle draggableTextListNoBgStyle;
29 | public static InfSliderStyle infSliderStyle;
30 | public static PopTableStyle tooltipBottomArrowStyle;
31 | public static PopTableStyle tooltipBottomLeftArrowStyle;
32 | public static PopTableStyle tooltipBottomRightArrowStyle;
33 | public static PopTableStyle tooltipTopArrowStyle;
34 | public static PopTableStyle tooltipRightArrowStyle;
35 | public static PopTableStyle tooltipLeftArrowStyle;
36 | public static EditableLabelStyle editableLabelStyle;
37 | public static PopColorPickerStyle popColorPickerStyle;
38 |
39 | public static void initializeStyles() {
40 | popColorPickerStyle = new PPcolorPickerStyle();
41 | lineGraphStyle = new PPlineGraphStyle();
42 | lineGraphBigStyle = new PPlineGraphBigStyle();
43 | colorGraphStyle = new PPcolorGraphStyle();
44 | spinnerStyle = new PPspinnerStyle();
45 | resizeWidgetStyle = new PPresizeWidgetStyle();
46 | draggableListStyle = new PPdraggableListStyle();
47 | draggableTextListStyle = new PPdraggableTextListStyle();
48 | draggableTextListNoBgStyle = new PPdraggableTextListNoBGStyle();
49 | infSliderStyle = new PPinfSliderStyle();
50 | tooltipBottomArrowStyle = new PopTableStyle(skin.get("tooltip-bottom-arrow", WindowStyle.class));
51 | tooltipBottomLeftArrowStyle = new PopTableStyle(skin.get("tooltip-bottom-left-arrow", WindowStyle.class));
52 | tooltipBottomRightArrowStyle = new PopTableStyle(skin.get("tooltip-bottom-right-arrow", WindowStyle.class));
53 | tooltipTopArrowStyle = new PopTableStyle(skin.get("tooltip-top-arrow", WindowStyle.class));
54 | tooltipRightArrowStyle = new PopTableStyle(skin.get("tooltip-right-arrow", WindowStyle.class));
55 | tooltipLeftArrowStyle = new PopTableStyle(skin.get("tooltip-left-arrow", WindowStyle.class));
56 | editableLabelStyle = new PPeditableLabelStyle();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/subpanels/CountSubPanel.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.subpanels;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Touchable;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Label;
5 | import com.badlogic.gdx.utils.Align;
6 | import com.ray3k.gdxparticleeditor.undo.UndoManager;
7 | import com.ray3k.gdxparticleeditor.undo.undoables.CountMaxUndoable;
8 | import com.ray3k.gdxparticleeditor.undo.undoables.CountMinUndoable;
9 | import com.ray3k.gdxparticleeditor.widgets.Panel;
10 | import com.ray3k.stripe.Spinner;
11 | import com.ray3k.stripe.Spinner.Orientation;
12 |
13 | import static com.ray3k.gdxparticleeditor.Core.selectedEmitter;
14 | import static com.ray3k.gdxparticleeditor.Core.skin;
15 | import static com.ray3k.gdxparticleeditor.Listeners.*;
16 | import static com.ray3k.gdxparticleeditor.widgets.styles.Styles.spinnerStyle;
17 | import static com.ray3k.gdxparticleeditor.widgets.styles.Styles.tooltipBottomArrowStyle;
18 |
19 | /**
20 | * A widget that allows the user to modify the Count value of the particle effect specifically. Numeric spinners for min
21 | * and max.
22 | */
23 | public class CountSubPanel extends Panel {
24 | public CountSubPanel() {
25 | setTouchable(Touchable.enabled);
26 |
27 | final var itemSpacing = 5;
28 | final var gap = 15;
29 | final var spinnerWidth = 50;
30 |
31 | tabTable.left();
32 | var label = new Label("Count", skin, "header-underline");
33 | tabTable.add(label);
34 |
35 | bodyTable.defaults().space(itemSpacing);
36 | bodyTable.left();
37 |
38 | label = new Label("Min:", skin);
39 | bodyTable.add(label);
40 |
41 | var minSpinner = new Spinner(selectedEmitter.getMinParticleCount(), 1, 0, Orientation.RIGHT_STACK, spinnerStyle);
42 | minSpinner.setHoldIncrement(10);
43 | bodyTable.add(minSpinner).width(spinnerWidth);
44 | addHandListener(minSpinner.getButtonMinus());
45 | addHandListener(minSpinner.getButtonPlus());
46 | addIbeamListener(minSpinner.getTextField());
47 | addUnfocusOnEnterKeyListener(minSpinner);
48 | addTooltip(minSpinner, "The minimum number of particles at all times", Align.top, Align.top, tooltipBottomArrowStyle);
49 | var changeListener = onChange(minSpinner, () -> UndoManager.add(new CountMinUndoable(selectedEmitter, minSpinner.getValueAsInt(), selectedEmitter.getMinParticleCount())));
50 | addInfiniteSlider(minSpinner, 1, 20, false, changeListener);
51 |
52 | label = new Label("Max:", skin);
53 | bodyTable.add(label).spaceLeft(gap);
54 |
55 | var maxSpinner = new Spinner(selectedEmitter.getMaxParticleCount(), 1, 0, Orientation.RIGHT_STACK, spinnerStyle);
56 | maxSpinner.setHoldIncrement(10);
57 | bodyTable.add(maxSpinner).width(spinnerWidth);
58 | addHandListener(maxSpinner.getButtonMinus());
59 | addHandListener(maxSpinner.getButtonPlus());
60 | addIbeamListener(maxSpinner.getTextField());
61 | addUnfocusOnEnterKeyListener(maxSpinner);
62 | addTooltip(maxSpinner, "The maximum number of particles allowed", Align.top, Align.top, tooltipBottomArrowStyle);
63 | changeListener = onChange(maxSpinner, () -> {
64 | var value = Math.max(0, maxSpinner.getValueAsInt());
65 | UndoManager.add(new CountMaxUndoable(selectedEmitter, value, selectedEmitter.getMaxParticleCount()));
66 | });
67 | addInfiniteSlider(maxSpinner, 1, 20, false, changeListener);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/gdxparticleeditor/widgets/tables/WelcomeTable.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.gdxparticleeditor.widgets.tables;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.graphics.Cursor.SystemCursor;
5 | import com.badlogic.gdx.scenes.scene2d.actions.Actions;
6 | import com.badlogic.gdx.scenes.scene2d.ui.*;
7 | import com.badlogic.gdx.utils.Align;
8 | import com.ray3k.gdxparticleeditor.Core;
9 | import com.ray3k.gdxparticleeditor.Settings;
10 | import com.ray3k.gdxparticleeditor.widgets.WelcomeCard;
11 | import com.ray3k.gdxparticleeditor.widgets.poptables.PopEditorSettings;
12 |
13 | import static com.ray3k.gdxparticleeditor.Core.*;
14 | import static com.ray3k.gdxparticleeditor.Listeners.*;
15 | import static com.ray3k.gdxparticleeditor.PresetActions.transition;
16 | import static com.ray3k.gdxparticleeditor.Settings.DEFAULT_OPEN_TO_SCREEN;
17 | import static com.ray3k.gdxparticleeditor.Settings.NAME_OPEN_TO_SCREEN;
18 | import static com.ray3k.gdxparticleeditor.widgets.styles.Styles.tooltipBottomRightArrowStyle;
19 |
20 | /**
21 | * The introductory table which highlights the app title and buttons to open the classic or wizard modes.
22 | */
23 | public class WelcomeTable extends Table {
24 | private Button settingsButton;
25 |
26 | public WelcomeTable() {
27 | shortcutManager.setDisabled(true);
28 | var stack = new Stack();
29 | add(stack).grow();
30 |
31 | var root = new Table();
32 | stack.add(root);
33 |
34 | var table = new Table();
35 | root.add(table);
36 |
37 | var image = new Image(skin, "title");
38 | table.add(image);
39 |
40 | table.row();
41 | var label = new Label(version, skin);
42 | table.add(label).expandX().right().padRight(10).padTop(5);
43 |
44 | root.row();
45 | table = new Table();
46 | root.add(table).spaceTop(100);
47 |
48 | table.row().spaceRight(70);
49 | var classicCard = new WelcomeCard("Classic", "The classic Particle Editor experience", skin.getDrawable("thumb-classic"), "Open Classic Mode");
50 | table.add(classicCard);
51 | addHandListener(classicCard);
52 |
53 | var wizardCard = new WelcomeCard("Wizard", "Simple with a large preview", skin.getDrawable("thumb-wizard"), "Open Wizard Mode");
54 | table.add(wizardCard);
55 | addHandListener(wizardCard);
56 |
57 | table.row();
58 | var checkbox = new CheckBox("Remember my choice", skin);
59 | checkbox.setChecked(!preferences.getString(NAME_OPEN_TO_SCREEN, DEFAULT_OPEN_TO_SCREEN).equals(DEFAULT_OPEN_TO_SCREEN));
60 | table.add(checkbox).space(25).right().colspan(2);
61 | addHandListener(checkbox);
62 | onChange(checkbox, () -> {
63 | if (!checkbox.isChecked()) {
64 | preferences.putString(NAME_OPEN_TO_SCREEN, "Welcome");
65 | preferences.flush();
66 | }
67 | });
68 |
69 | root = new Table();
70 | stack.add(root);
71 |
72 | settingsButton = new Button(skin, "settings");
73 | root.add(settingsButton).expand().bottom().right().padRight(20).padBottom(10);
74 | addHandListener(settingsButton);
75 | addTooltip(settingsButton, "Open the Editor Settings dialog", Align.top, Align.topLeft, tooltipBottomRightArrowStyle, false);
76 | onChange(settingsButton, () -> {
77 | Gdx.input.setInputProcessor(foregroundStage);
78 | Gdx.graphics.setSystemCursor(SystemCursor.Arrow);
79 | var pop = new PopEditorSettings();
80 | pop.show(foregroundStage);
81 | });
82 |
83 | onChange(classicCard, () -> {
84 | if (checkbox.isChecked()) {
85 | preferences.putString(NAME_OPEN_TO_SCREEN, "Classic");
86 | preferences.flush();
87 | }
88 | Core.openTable = "Classic";
89 | transition(this, new ClassicTable(), Align.top);
90 | shortcutManager.setDisabled(false);
91 | shortcutManager.setScope(Settings.CLASSIC_SCOPE);
92 | fadeSettingsButton();
93 | });
94 |
95 | onChange(wizardCard, () -> {
96 | if (checkbox.isChecked()) {
97 | preferences.putString(NAME_OPEN_TO_SCREEN, "Wizard");
98 | preferences.flush();
99 | }
100 | Core.openTable = "Wizard";
101 | transition(this, new WizardTable(), Align.top);
102 | shortcutManager.setDisabled(false);
103 | shortcutManager.setScope(Settings.WIZARD_SCOPE);
104 | fadeSettingsButton();
105 | });
106 | }
107 |
108 | private void fadeSettingsButton() {
109 | settingsButton.addAction(Actions.fadeOut(.3f));
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/stripe/PopTableHoverListener.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.stripe;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.*;
4 | import com.badlogic.gdx.scenes.scene2d.ui.Skin;
5 | import com.badlogic.gdx.scenes.scene2d.utils.Disableable;
6 | import com.ray3k.stripe.PopTable.PopTableStyle;
7 | import com.ray3k.stripe.PopTable.TableShowHideListener;
8 |
9 | public class PopTableHoverListener extends InputListener {
10 | protected PopTable popTable;
11 | public boolean hideOnExit;
12 | private final int align;
13 | private final int edge;
14 |
15 | public PopTableHoverListener(int edge, int align, Skin skin) {
16 | this(edge, align, skin.get(PopTableStyle.class));
17 | }
18 |
19 | public PopTableHoverListener(int edge, int align, Skin skin, String style) {
20 | this(edge, align, skin.get(style, PopTableStyle.class));
21 | }
22 |
23 | public PopTableHoverListener(int edge, int align, PopTableStyle style) {
24 | hideOnExit = true;
25 | popTable = new PopTable(style);
26 | popTable.setModal(false);
27 | popTable.setTouchable(Touchable.disabled);
28 | this.edge = edge;
29 | this.align = align;
30 | popTable.addListener(new TableShowHideListener() {
31 | @Override
32 | public void tableShown(Event event) {
33 | PopTableHoverListener.this.tableShown(event);
34 | }
35 |
36 | @Override
37 | public void tableHidden(Event event) {
38 | PopTableHoverListener.this.tableHidden(event);
39 | }
40 | });
41 | }
42 |
43 | @Override
44 | public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
45 | if (popTable.isHidden()) {
46 | if (fromActor == null || !event.getListenerActor().isAscendantOf(fromActor)) {
47 | Stage stage = event.getListenerActor().getStage();
48 | Actor actor = event.getListenerActor();
49 |
50 | if (actor instanceof Disableable) {
51 | if (((Disableable) actor).isDisabled()) return;
52 | }
53 |
54 | popTable.show(stage);
55 | popTable.attachToActor(actor, edge, align);
56 |
57 |
58 | popTable.moveToInsideStage();
59 | }
60 | }
61 | }
62 |
63 | @Override
64 | public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
65 | if (hideOnExit && !popTable.isHidden()) {
66 | if (toActor == null || !event.getListenerActor().isAscendantOf(toActor)) {
67 | popTable.hide();
68 | }
69 | }
70 | }
71 |
72 | public PopTable getPopTable() {
73 | return popTable;
74 | }
75 |
76 | /**
77 | * Override this method to be performed when the popTable is hidden or dismissed.
78 | * @param event The event associated with the table being shown.
79 | */
80 | public void tableShown(Event event) {
81 |
82 | }
83 |
84 | /**
85 | * Override this method to be performed when the popTable is hidden or dismissed.
86 | * @param event The event associated with the table being hidden.
87 | */
88 | public void tableHidden(Event event) {
89 |
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/stripe/ScrollFocusListener.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.stripe;
2 |
3 | import com.badlogic.gdx.scenes.scene2d.Actor;
4 | import com.badlogic.gdx.scenes.scene2d.InputEvent;
5 | import com.badlogic.gdx.scenes.scene2d.InputListener;
6 | import com.badlogic.gdx.scenes.scene2d.Stage;
7 | import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
8 |
9 | /**
10 | * Add ScrollFocusListener to any scrollable widget that you want to set as the Stage's scrollFocus once the user mouses
11 | * over the widget.
12 | */
13 | public class ScrollFocusListener extends InputListener {
14 | private Stage stage;
15 |
16 | public ScrollFocusListener(Stage stage) {
17 | this.stage = stage;
18 | }
19 |
20 | @Override
21 | public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
22 | var scrollFocus = stage.getScrollFocus();
23 | var actor = event.getListenerActor();
24 | if (actor instanceof ScrollPane) {
25 | var scrollPane = (ScrollPane) actor;
26 | if (!scrollPane.isScrollY() && !scrollPane.isScrollX()) return;
27 | }
28 | if (scrollFocus == null || scrollFocus != actor && !scrollFocus.isDescendantOf(actor)) {
29 | stage.setScrollFocus(event.getListenerActor());
30 | }
31 | }
32 |
33 | @Override
34 | public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
35 | var actor = event.getListenerActor();
36 | if (stage.getScrollFocus() == actor && (toActor == null || !toActor.isDescendantOf(actor))) {
37 | stage.setScrollFocus(null);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/java/com/ray3k/stripe/ViewportWidget.java:
--------------------------------------------------------------------------------
1 | package com.ray3k.stripe;
2 |
3 | import com.badlogic.gdx.Gdx;
4 | import com.badlogic.gdx.math.MathUtils;
5 | import com.badlogic.gdx.math.Vector2;
6 | import com.badlogic.gdx.scenes.scene2d.ui.Widget;
7 | import com.badlogic.gdx.utils.viewport.Viewport;
8 |
9 | /**
10 | * A widget that allows you to embed an entire viewport within your UI. This is an excellent tool to integrate your
11 | * games into a UI instead of just overlaying the UI on top of it. Make sure to render your game assets after calling
12 | * stage.act() in the render method to prevent position lag.
13 | */
14 | public class ViewportWidget extends Widget {
15 | public Viewport viewport;
16 | private final static Vector2 temp = new Vector2();
17 |
18 | public ViewportWidget(Viewport viewport) {
19 | this.viewport = viewport;
20 | }
21 |
22 | /**
23 | * Updates the viewport's bounds to match the size and position of the widget. Applies the viewport. Call before
24 | * drawing to the viewport.
25 | * @param centerCamera
26 | */
27 | public void updateViewport(boolean centerCamera) {
28 | temp.set(MathUtils.round(getWidth()), MathUtils.round(getHeight()));
29 | if (getStage() != null) getStage().getViewport().project(temp);
30 |
31 | viewport.update(MathUtils.round(temp.x), MathUtils.round(temp.y), centerCamera);
32 |
33 | int viewportOriginalX = viewport.getScreenX();
34 | int viewportOriginalY = viewport.getScreenY();
35 | temp.set(0, 0);
36 | localToScreenCoordinates(temp);
37 | viewport.setScreenPosition(viewportOriginalX + MathUtils.round(temp.x), viewportOriginalY + MathUtils.round(Gdx.graphics.getHeight() - temp.y));
38 | viewport.apply(centerCamera);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/resources/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/src/main/resources/icon128.png
--------------------------------------------------------------------------------
/core/src/main/resources/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/src/main/resources/icon16.png
--------------------------------------------------------------------------------
/core/src/main/resources/icon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/src/main/resources/icon32.png
--------------------------------------------------------------------------------
/core/src/main/resources/icon64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/core/src/main/resources/icon64.png
--------------------------------------------------------------------------------
/core/src/main/resources/version:
--------------------------------------------------------------------------------
1 | 1.0.9
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.daemon=true
2 | org.gradle.jvmargs=-Xms512M -Xmx1G -XX:MaxMetaspaceSize=1G
3 | org.gradle.configureondemand=false
4 | lombokVersion=1.18.28
5 | gdxVersion=1.12.1
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libgdx/gdx-particle-editor/9b0aa9c8a2208c510a9d8a6b26c08f80b6aaf7dc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if %ERRORLEVEL% equ 0 goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if %ERRORLEVEL% equ 0 goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | set EXIT_CODE=%ERRORLEVEL%
84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
86 | exit /b %EXIT_CODE%
87 |
88 | :mainEnd
89 | if "%OS%"=="Windows_NT" endlocal
90 |
91 | :omega
92 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'core'
2 |
--------------------------------------------------------------------------------