gdx-studio
git clone https://git.pyrossh.dev/gdx-studio
An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop
src/gdxstudio/panel/StudioPanel.java
| a9b2a64 | 1 | package gdxstudio.panel; |
| a9b2a64 | 2 | |
| a9b2a64 | 3 | import gdxstudio.Content; |
| a9b2a64 | 4 | import gdxstudio.Frame; |
| a9b2a64 | 5 | import gdxstudio.GdxStudio; |
| a9b2a64 | 6 | import gdxstudio.Style; |
| a9b2a64 | 7 | |
| a9b2a64 | 8 | import java.awt.Color; |
| a62d533 | 9 | import java.awt.Dimension; |
| a62d533 | 10 | import java.awt.Graphics; |
| a62d533 | 11 | import java.awt.Image; |
| a62d533 | 12 | import java.awt.Insets; |
| a62d533 | 13 | import java.awt.datatransfer.DataFlavor; |
| a62d533 | 14 | import java.awt.datatransfer.Transferable; |
| a62d533 | 15 | import java.awt.dnd.DnDConstants; |
| a62d533 | 16 | import java.awt.dnd.DropTarget; |
| a62d533 | 17 | import java.awt.dnd.DropTargetDropEvent; |
| a62d533 | 18 | import java.io.File; |
| a62d533 | 19 | import java.nio.ByteBuffer; |
| a62d533 | 20 | |
| a62d533 | 21 | import javax.swing.JPanel; |
| a62d533 | 22 | import javax.swing.JScrollPane; |
| a62d533 | 23 | |
| a9b2a64 | 24 | import org.lwjgl.LWJGLException; |
| a9b2a64 | 25 | import org.lwjgl.opengl.GLContext; |
| a9b2a64 | 26 | |
| a9b2a64 | 27 | import scene2d.Asset; |
| a9b2a64 | 28 | import scene2d.Effect; |
| a9b2a64 | 29 | import scene2d.EffectType; |
| a9b2a64 | 30 | import scene2d.ImageJson; |
| a9b2a64 | 31 | import scene2d.InterpolationType; |
| a9b2a64 | 32 | import scene2d.Map; |
| a9b2a64 | 33 | import scene2d.Scene; |
| a9b2a64 | 34 | import scene2d.Sprite; |
| a9b2a64 | 35 | import web.laf.lite.layout.HorizontalFlowLayout; |
| a62d533 | 36 | import web.laf.lite.layout.VerticalFlowLayout; |
| a62d533 | 37 | import web.laf.lite.utils.UIUtils; |
| a9b2a64 | 38 | import web.laf.lite.widget.CenterPanel; |
| a62d533 | 39 | |
| a62d533 | 40 | import com.badlogic.gdx.Gdx; |
| a62d533 | 41 | import com.badlogic.gdx.backends.lwjgl.LwjglAWTCanvas; |
| a9b2a64 | 42 | import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; |
| a62d533 | 43 | import com.badlogic.gdx.backends.lwjgl.LwjglCanvas; |
| a62d533 | 44 | import com.badlogic.gdx.files.FileHandle; |
| a62d533 | 45 | import com.badlogic.gdx.graphics.GL20; |
| a62d533 | 46 | import com.badlogic.gdx.graphics.Pixmap; |
| a62d533 | 47 | import com.badlogic.gdx.graphics.Pixmap.Format; |
| a62d533 | 48 | import com.badlogic.gdx.graphics.PixmapIO; |
| a62d533 | 49 | import com.badlogic.gdx.scenes.scene2d.Actor; |
| a62d533 | 50 | import com.badlogic.gdx.scenes.scene2d.ui.Button; |
| a62d533 | 51 | import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; |
| a62d533 | 52 | import com.badlogic.gdx.scenes.scene2d.ui.Dialog; |
| a62d533 | 53 | import com.badlogic.gdx.scenes.scene2d.ui.Label; |
| a62d533 | 54 | import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle; |
| a62d533 | 55 | import com.badlogic.gdx.scenes.scene2d.ui.List; |
| a62d533 | 56 | import com.badlogic.gdx.scenes.scene2d.ui.SelectBox; |
| a62d533 | 57 | import com.badlogic.gdx.scenes.scene2d.ui.Slider; |
| a62d533 | 58 | import com.badlogic.gdx.scenes.scene2d.ui.Table; |
| a62d533 | 59 | import com.badlogic.gdx.scenes.scene2d.ui.TextButton; |
| a62d533 | 60 | import com.badlogic.gdx.scenes.scene2d.ui.TextField; |
| a62d533 | 61 | import com.badlogic.gdx.scenes.scene2d.ui.Touchpad; |
| a62d533 | 62 | import com.badlogic.gdx.tools.hiero.HieroPanel; |
| a62d533 | 63 | import com.badlogic.gdx.tools.particleeditor.ParticlePanel; |
| a62d533 | 64 | import com.badlogic.gdx.tools.particleeditor.ParticleRenderer; |
| 7c84877 | 65 | import com.badlogic.gdx.utils.Timer.Task; |
| a62d533 | 66 | |
| a62d533 | 67 | |
| a62d533 | 68 | final public class StudioPanel extends JPanel {
|
| a62d533 | 69 | private static final long serialVersionUID = 1L; |
| a62d533 | 70 | LwjglCanvas can; |
| a9b2a64 | 71 | public LwjglAWTCanvas canvas; |
| a9b2a64 | 72 | JPanel hbox; |
| a9b2a64 | 73 | CenterPanel centerPanel; |
| a9b2a64 | 74 | JScrollPane scrollPane; |
| a9b2a64 | 75 | LwjglApplicationConfiguration config2 = new LwjglApplicationConfiguration(); |
| a62d533 | 76 | |
| a62d533 | 77 | Image img; |
| a62d533 | 78 | public StudioPanel(){
|
| a62d533 | 79 | super(new VerticalFlowLayout()); |
| a9b2a64 | 80 | hbox = new JPanel(new HorizontalFlowLayout()); |
| a9b2a64 | 81 | hbox.add(new HeaderLabel("Screen Size"));
|
| a9b2a64 | 82 | hbox.add(new HeaderLabel("Target Size"));
|
| a62d533 | 83 | UIUtils.setMargin(this, new Insets(15,15,15,15)); |
| a9b2a64 | 84 | config2.width = 640; |
| a9b2a64 | 85 | config2.height = 320; |
| a9b2a64 | 86 | config2.fullscreen = false; |
| a9b2a64 | 87 | config2.useGL20 = false; |
| a62d533 | 88 | } |
| a62d533 | 89 | |
| a62d533 | 90 | |
| a62d533 | 91 | |
| a62d533 | 92 | @Override |
| a62d533 | 93 | public void paint(Graphics g){
|
| a62d533 | 94 | if(!isOpaque()) |
| a62d533 | 95 | Style.drawScreen(g, getWidth(), getHeight()); |
| a62d533 | 96 | super.paint(g); |
| a62d533 | 97 | |
| a62d533 | 98 | } |
| a62d533 | 99 | |
| a62d533 | 100 | String config = "{"
|
| a62d533 | 101 | +"title: GdxStudio," |
| a62d533 | 102 | +"keepAspectRatio: false," |
| a62d533 | 103 | +"showFPS: false," |
| a62d533 | 104 | +"loggingEnabled: true," |
| a62d533 | 105 | +"}"; |
| a62d533 | 106 | |
| a62d533 | 107 | public void createHieroCanvas(){
|
| a62d533 | 108 | setOpaque(true); |
| a62d533 | 109 | removeAll(); |
| a62d533 | 110 | HieroPanel panel = new HieroPanel(); |
| a62d533 | 111 | canvas = new LwjglAWTCanvas(new HieroPanel.FontRenderer() , false); |
| a62d533 | 112 | HieroPanel.gamePanel.add(canvas.getCanvas()); |
| a62d533 | 113 | JScrollPane scrollPane = new JScrollPane(panel); |
| a62d533 | 114 | scrollPane.setPreferredSize(new Dimension(860, 650)); |
| a62d533 | 115 | UIUtils.setDrawBorder(scrollPane, false); |
| a62d533 | 116 | add(scrollPane); |
| a62d533 | 117 | } |
| a62d533 | 118 | |
| a62d533 | 119 | public void createParticleCanvas(){
|
| a62d533 | 120 | setOpaque(true); |
| a62d533 | 121 | removeAll(); |
| a62d533 | 122 | ParticlePanel panel = new ParticlePanel(); |
| a62d533 | 123 | canvas = new LwjglAWTCanvas(new ParticleRenderer(panel) , false); |
| a62d533 | 124 | panel.initializeComponents(canvas); |
| a62d533 | 125 | JScrollPane scrollPane = new JScrollPane(panel); |
| a62d533 | 126 | scrollPane.setPreferredSize(new Dimension(860, 650)); |
| a62d533 | 127 | UIUtils.setDrawBorder(scrollPane, false); |
| a62d533 | 128 | add(scrollPane); |
| a62d533 | 129 | } |
| a62d533 | 130 | |
| a62d533 | 131 | public void createStudioCanvas(){
|
| a62d533 | 132 | removeAll(); |
| a9b2a64 | 133 | GdxStudio.log("Creating Studio Canvas");
|
| a62d533 | 134 | try{
|
| a9b2a64 | 135 | Scene.configJson = Scene.jsonReader.parse(config); |
| a9b2a64 | 136 | Scene.debug = true; |
| a62d533 | 137 | Scene.scenesMap.clear(); |
| a9b2a64 | 138 | Scene.scenesMap.put("gdxstudio.SceneEditor", "");
|
| a62d533 | 139 | setOpaque(false); |
| a9b2a64 | 140 | canvas = new LwjglAWTCanvas(Scene.app , false); |
| a9b2a64 | 141 | scrollPane = new JScrollPane(canvas.getCanvas()); |
| a62d533 | 142 | scrollPane.setPreferredSize(new Dimension(800, 480)); |
| a62d533 | 143 | UIUtils.setDrawBorder(scrollPane, false); |
| a9b2a64 | 144 | Style.setScreenSize(scrollPane.getPreferredSize().width, scrollPane.getPreferredSize().height); |
| a9b2a64 | 145 | centerPanel = new CenterPanel(scrollPane, true, false); |
| a9b2a64 | 146 | centerPanel.setBackground(Color.black); |
| a9b2a64 | 147 | UIUtils.setUndecorated(centerPanel, true); |
| a9b2a64 | 148 | UIUtils.setMargin(centerPanel, new Insets(0,0,0,0)); |
| a9b2a64 | 149 | add(centerPanel); |
| a9b2a64 | 150 | validate(); |
| a9b2a64 | 151 | Style.setScreenPosition(scrollPane.getLocation().x, scrollPane.getLocation().y); |
| a62d533 | 152 | canvas.getCanvas().setDropTarget(new DropTarget() {
|
| a62d533 | 153 | private static final long serialVersionUID = 1L; |
| a62d533 | 154 | public synchronized void drop(DropTargetDropEvent event) {
|
| a62d533 | 155 | try{
|
| a62d533 | 156 | Transferable transferable = event.getTransferable(); |
| a62d533 | 157 | if( transferable.isDataFlavorSupported(DataFlavor.stringFlavor )){
|
| a62d533 | 158 | event.acceptDrop( DnDConstants.ACTION_MOVE ); |
| a62d533 | 159 | String s = (String)transferable.getTransferData(DataFlavor.stringFlavor); |
| a62d533 | 160 | createActor(s); |
| a62d533 | 161 | event.getDropTargetContext().dropComplete(true); |
| a62d533 | 162 | } |
| a62d533 | 163 | else{
|
| a62d533 | 164 | event.rejectDrop(); |
| a62d533 | 165 | } |
| a62d533 | 166 | } |
| a62d533 | 167 | catch( Exception exception ){
|
| a62d533 | 168 | System.err.println( "Exception" + exception.getMessage() ); |
| a62d533 | 169 | event.rejectDrop(); |
| a62d533 | 170 | } |
| a62d533 | 171 | } |
| a62d533 | 172 | }); |
| a62d533 | 173 | Asset.save(); |
| a62d533 | 174 | }catch(Exception ex){
|
| a62d533 | 175 | ex.printStackTrace(); |
| a62d533 | 176 | } |
| a62d533 | 177 | } |
| a62d533 | 178 | |
| a9b2a64 | 179 | public void setGdxScreenSize(int width, int height){
|
| a9b2a64 | 180 | removeAll(); |
| a9b2a64 | 181 | canvas.getCanvas().setSize(width, height); |
| a9b2a64 | 182 | scrollPane = new JScrollPane(canvas.getCanvas()); |
| a9b2a64 | 183 | scrollPane.setPreferredSize(new Dimension(width, height)); |
| a9b2a64 | 184 | UIUtils.setDrawBorder(scrollPane, false); |
| a9b2a64 | 185 | Style.setScreenSize(scrollPane.getPreferredSize().width, scrollPane.getPreferredSize().height); |
| a9b2a64 | 186 | scrollPane.setPreferredSize(new Dimension(width, height)); |
| a9b2a64 | 187 | centerPanel = new CenterPanel(scrollPane, true, false); |
| a9b2a64 | 188 | centerPanel.setBackground(Color.black); |
| a9b2a64 | 189 | UIUtils.setUndecorated(centerPanel, true); |
| a9b2a64 | 190 | UIUtils.setMargin(centerPanel, new Insets(0,0,0,0)); |
| a9b2a64 | 191 | add(centerPanel); |
| a9b2a64 | 192 | validate(); |
| a9b2a64 | 193 | Style.setScreenPosition(scrollPane.getLocation().x, scrollPane.getLocation().y); |
| a9b2a64 | 194 | canvas.makeCurrent(); |
| a9b2a64 | 195 | try {
|
| a9b2a64 | 196 | GLContext.useContext(canvas); |
| a9b2a64 | 197 | } catch (LWJGLException e) {
|
| a9b2a64 | 198 | e.printStackTrace(); |
| a9b2a64 | 199 | } |
| a9b2a64 | 200 | } |
| a9b2a64 | 201 | |
| a9b2a64 | 202 | public void revalidateScreenPosition(){
|
| a9b2a64 | 203 | if(scrollPane != null){
|
| a9b2a64 | 204 | validate(); |
| a9b2a64 | 205 | Style.setScreenPosition(canvas.getCanvas().getLocation().x, canvas.getCanvas().getLocation().y); |
| a9b2a64 | 206 | } |
| a9b2a64 | 207 | } |
| a9b2a64 | 208 | |
| a62d533 | 209 | public void destroyCanvas(){
|
| a9b2a64 | 210 | GdxStudio.log("Destroying Scene Canvas");
|
| a62d533 | 211 | if(canvas != null){
|
| a62d533 | 212 | remove(canvas.getCanvas()); |
| a62d533 | 213 | canvas.stop(); |
| a62d533 | 214 | canvas = null; |
| a62d533 | 215 | } |
| a62d533 | 216 | } |
| a62d533 | 217 | |
| a62d533 | 218 | private int getNameCount(Actor actor){
|
| a62d533 | 219 | int count = 1; |
| a9b2a64 | 220 | for(Actor child: Scene.getCurrentScene().getChildren()) |
| a62d533 | 221 | if(actor.getClass().equals(child.getClass())) count++; |
| a62d533 | 222 | return count; |
| a62d533 | 223 | } |
| a62d533 | 224 | |
| a62d533 | 225 | |
| 7c84877 | 226 | public void setName(final Actor actor){
|
| 7c84877 | 227 | com.badlogic.gdx.utils.Timer.schedule(new Task(){
|
| 7c84877 | 228 | @Override |
| 7c84877 | 229 | public void run() {
|
| 7c84877 | 230 | String name = actor.getClass().getSimpleName()+getNameCount(actor); |
| a9b2a64 | 231 | if(Scene.getCurrentScene().findActor(name) == null) |
| 7c84877 | 232 | actor.setName(name); |
| 7c84877 | 233 | else |
| 7c84877 | 234 | actor.setName(name+"_1"); |
| a9b2a64 | 235 | actor.setX(Scene.mouse.x-actor.getWidth()/2); |
| a9b2a64 | 236 | actor.setY(Scene.mouse.y-actor.getHeight()/2); |
| a9b2a64 | 237 | Scene.getCurrentScene().addActor(actor); |
| 7c84877 | 238 | Frame.actorPanel.addActor(actor.getName()); |
| a9b2a64 | 239 | Scene.isDirty = true; |
| 7c84877 | 240 | Effect.createEffect(actor, EffectType.ScaleInOut, 1.5f, 0.5f, InterpolationType.Linear); |
| 7c84877 | 241 | } |
| 7c84877 | 242 | }, 0.1f); |
| a62d533 | 243 | } |
| a62d533 | 244 | |
| a62d533 | 245 | public void createActor(String type){
|
| a62d533 | 246 | switch(type){
|
| a62d533 | 247 | case "Label": |
| a62d533 | 248 | if(Asset.fontMap.size != 0){
|
| a62d533 | 249 | LabelStyle ls = new LabelStyle(); |
| a62d533 | 250 | ls.font = Asset.fontMap.firstValue(); |
| a62d533 | 251 | Label label = new Label("Text", ls);
|
| a62d533 | 252 | setName(label); |
| a62d533 | 253 | } |
| a62d533 | 254 | break; |
| a62d533 | 255 | case "Image": |
| a62d533 | 256 | if(Asset.texMap.size != 0){
|
| a62d533 | 257 | setName(new ImageJson(Asset.texMap.firstKey())); |
| a62d533 | 258 | } |
| a62d533 | 259 | break; |
| a62d533 | 260 | case "Texture":setName(new ImageJson(Content.assetPanel.list.getSelectedValue()));break; |
| a62d533 | 261 | case "Sprite":setName(new Sprite(1f, Asset.texMap.firstKey()));break; |
| a62d533 | 262 | case "Particle": |
| a62d533 | 263 | //ParticleEffect pe = new ParticleEffect(); |
| a62d533 | 264 | //pe.load(effectFile, imagesDir); |
| a62d533 | 265 | break; |
| a62d533 | 266 | |
| a62d533 | 267 | case "Button":setName(new Button(Asset.skin));break; |
| a62d533 | 268 | case "TextButton":setName(new TextButton("Text", Asset.skin));break;
|
| a62d533 | 269 | case "TextField":setName(new TextField("", Asset.skin));break;
|
| a62d533 | 270 | case "Table":setName(new Table(Asset.skin));break; |
| a62d533 | 271 | case "CheckBox":setName(new CheckBox("Check", Asset.skin));break;
|
| a62d533 | 272 | case "SelectBox":setName(new SelectBox(new String[]{"First","Second","Third"}, Asset.skin));break;
|
| a62d533 | 273 | case "List":setName(new List(new String[]{"First","Second","Third"}, Asset.skin));break;
|
| a62d533 | 274 | case "Slider":setName(new Slider(0, 10, 1, false, Asset.skin));break; |
| a62d533 | 275 | case "Dialog":setName(new Dialog("Title", Asset.skin));break;
|
| a62d533 | 276 | case "Touchpad":setName(new Touchpad(5, Asset.skin));break; |
| a62d533 | 277 | case "Map":setName(new Map(1, 24));break; |
| a62d533 | 278 | case "None":break; |
| a62d533 | 279 | default:break; |
| a62d533 | 280 | } |
| a62d533 | 281 | } |
| a62d533 | 282 | |
| a62d533 | 283 | public static void updateAssets(){
|
| a62d533 | 284 | StringBuilder sb = new StringBuilder(); |
| a62d533 | 285 | for(String filename: new File(Asset.basePath+"font").list()){
|
| a62d533 | 286 | if(filename.endsWith(".fnt")){
|
| a9b2a64 | 287 | GdxStudio.log("Loading :"+filename);
|
| a62d533 | 288 | sb.append(filename); |
| a62d533 | 289 | sb.append(",");
|
| a62d533 | 290 | } |
| a62d533 | 291 | } |
| a62d533 | 292 | Asset.assetMap.put("font", sb.toString());
|
| a62d533 | 293 | sb = new StringBuilder(); |
| a62d533 | 294 | for(String filename: new File(Asset.basePath+"atlas").list()){
|
| a62d533 | 295 | if(filename.endsWith(".atlas")){
|
| a9b2a64 | 296 | GdxStudio.log("Loading :"+filename);
|
| a62d533 | 297 | sb.append(filename); |
| a62d533 | 298 | sb.append(",");
|
| a62d533 | 299 | } |
| a62d533 | 300 | } |
| a62d533 | 301 | Asset.assetMap.put("atlas", sb.toString());
|
| a62d533 | 302 | sb = new StringBuilder(); |
| a62d533 | 303 | for(String filename: new File(Asset.basePath+"sound").list()){
|
| a62d533 | 304 | if(filename.endsWith(".mp3")){
|
| a9b2a64 | 305 | GdxStudio.log("Loading :"+filename);
|
| a62d533 | 306 | sb.append(filename); |
| a62d533 | 307 | sb.append(",");
|
| a62d533 | 308 | } |
| a62d533 | 309 | } |
| a62d533 | 310 | Asset.assetMap.put("sound", sb.toString());
|
| a62d533 | 311 | sb = new StringBuilder(); |
| a62d533 | 312 | for(String filename: new File(Asset.basePath+"music").list()){
|
| a62d533 | 313 | if(filename.endsWith(".mp3")){
|
| a9b2a64 | 314 | GdxStudio.log("Loading :"+filename);
|
| a62d533 | 315 | sb.append(filename); |
| a62d533 | 316 | sb.append(",");
|
| a62d533 | 317 | } |
| a62d533 | 318 | } |
| a62d533 | 319 | Asset.assetMap.put("music", sb.toString());
|
| a9b2a64 | 320 | sb = new StringBuilder(); |
| a9b2a64 | 321 | for(String filename: new File(Asset.basePath+"model").list()){
|
| a9b2a64 | 322 | if(filename.endsWith(".obj") || filename.endsWith(".g3db")){
|
| a9b2a64 | 323 | GdxStudio.log("Loading :"+filename);
|
| a9b2a64 | 324 | Asset.modelMap.add(filename); |
| a9b2a64 | 325 | } |
| a9b2a64 | 326 | } |
| a62d533 | 327 | } |
| a62d533 | 328 | |
| a62d533 | 329 | private static int counter = 1; |
| a62d533 | 330 | public static void saveScreenshot(){
|
| a62d533 | 331 | try{
|
| a62d533 | 332 | FileHandle fh; |
| a62d533 | 333 | do{
|
| a62d533 | 334 | fh = new FileHandle("shots/shot" + counter++ + ".png");
|
| a62d533 | 335 | }while (fh.exists()); |
| a62d533 | 336 | Pixmap pixmap = getScreenshot(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false); |
| a62d533 | 337 | PixmapIO.writePNG(fh, pixmap); |
| a62d533 | 338 | pixmap.dispose(); |
| a62d533 | 339 | }catch (Exception e){
|
| a62d533 | 340 | } |
| a62d533 | 341 | } |
| a62d533 | 342 | |
| a62d533 | 343 | private static Pixmap getScreenshot(int x, int y, int w, int h, boolean flipY){
|
| a62d533 | 344 | Gdx.gl.glPixelStorei(GL20.GL_PACK_ALIGNMENT, 1); |
| a62d533 | 345 | |
| a62d533 | 346 | final Pixmap pixmap = new Pixmap(w, h, Format.RGBA8888); |
| a62d533 | 347 | ByteBuffer pixels = pixmap.getPixels(); |
| a62d533 | 348 | Gdx.gl.glReadPixels(x, y, w, h, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixels); |
| a62d533 | 349 | |
| a62d533 | 350 | final int numBytes = w * h * 4; |
| a62d533 | 351 | byte[] lines = new byte[numBytes]; |
| a62d533 | 352 | if (flipY){
|
| a62d533 | 353 | pixels.clear(); |
| a62d533 | 354 | pixels.get(lines); |
| a62d533 | 355 | }else{
|
| a62d533 | 356 | final int numBytesPerLine = w * 4; |
| a62d533 | 357 | for (int i = 0; i < h; i++){
|
| a62d533 | 358 | pixels.position((h - i - 1) * numBytesPerLine); |
| a62d533 | 359 | pixels.get(lines, i * numBytesPerLine, numBytesPerLine); |
| a62d533 | 360 | } |
| a62d533 | 361 | pixels.clear(); |
| a62d533 | 362 | pixels.put(lines); |
| a62d533 | 363 | } |
| a62d533 | 364 | return pixmap; |
| a62d533 | 365 | } |
| a62d533 | 366 | } |