PageRenderTime 66ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/v0.07.2/src/SunflowGUI.java

https://bitbucket.org/sandos/sunflow-patches
Java | 1228 lines | 1165 code | 39 blank | 24 comment | 195 complexity | 0e3ba82ff792ecf34330f5b148970240 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. import java.awt.BorderLayout;
  2. import java.awt.Dimension;
  3. import java.awt.FlowLayout;
  4. import java.awt.Toolkit;
  5. import java.awt.datatransfer.DataFlavor;
  6. import java.awt.datatransfer.Transferable;
  7. import java.awt.event.ActionEvent;
  8. import java.awt.event.ActionListener;
  9. import java.beans.PropertyVetoException;
  10. import java.io.BufferedReader;
  11. import java.io.File;
  12. import java.io.FileNotFoundException;
  13. import java.io.FileReader;
  14. import java.io.FileWriter;
  15. import java.io.IOException;
  16. import java.util.List;
  17. import javax.swing.BorderFactory;
  18. import javax.swing.JButton;
  19. import javax.swing.JCheckBoxMenuItem;
  20. import javax.swing.JComponent;
  21. import javax.swing.JDesktopPane;
  22. import javax.swing.JFileChooser;
  23. import javax.swing.JInternalFrame;
  24. import javax.swing.JMenu;
  25. import javax.swing.JMenuBar;
  26. import javax.swing.JMenuItem;
  27. import javax.swing.JOptionPane;
  28. import javax.swing.JPanel;
  29. import javax.swing.JProgressBar;
  30. import javax.swing.JScrollPane;
  31. import javax.swing.JSeparator;
  32. import javax.swing.JTextArea;
  33. import javax.swing.KeyStroke;
  34. import javax.swing.ScrollPaneConstants;
  35. import javax.swing.SwingUtilities;
  36. import javax.swing.TransferHandler;
  37. import javax.swing.filechooser.FileFilter;
  38. import javax.swing.plaf.metal.DefaultMetalTheme;
  39. import javax.swing.plaf.metal.MetalLookAndFeel;
  40. import org.sunflow.Benchmark;
  41. import org.sunflow.RealtimeBenchmark;
  42. import org.sunflow.SunflowAPI;
  43. import org.sunflow.core.Display;
  44. import org.sunflow.core.Shader;
  45. import org.sunflow.core.TextureCache;
  46. import org.sunflow.core.accel.KDTree;
  47. import org.sunflow.core.display.FileDisplay;
  48. import org.sunflow.core.display.FrameDisplay;
  49. import org.sunflow.core.display.ImgPipeDisplay;
  50. import org.sunflow.core.display.OpenExrDisplay;
  51. import org.sunflow.core.primitive.TriangleMesh;
  52. import org.sunflow.core.shader.AmbientOcclusionShader;
  53. import org.sunflow.core.shader.IDShader;
  54. import org.sunflow.core.shader.NormalShader;
  55. import org.sunflow.core.shader.PrimIDShader;
  56. import org.sunflow.core.shader.QuickGrayShader;
  57. import org.sunflow.core.shader.UVShader;
  58. import org.sunflow.core.shader.WireframeShader;
  59. import org.sunflow.image.Color;
  60. import org.sunflow.system.ImagePanel;
  61. import org.sunflow.system.Timer;
  62. import org.sunflow.system.UI;
  63. import org.sunflow.system.UserInterface;
  64. import org.sunflow.system.UI.Module;
  65. import org.sunflow.system.UI.PrintLevel;
  66. @SuppressWarnings("serial")
  67. public class SunflowGUI extends javax.swing.JFrame implements UserInterface {
  68. private static final int DEFAULT_WIDTH = 1024;
  69. private static final int DEFAULT_HEIGHT = 768;
  70. private JPanel jPanel3;
  71. private JScrollPane jScrollPane1;
  72. private JMenuItem exitMenuItem;
  73. private JSeparator jSeparator2;
  74. private JPanel jPanel1;
  75. private JButton renderButton;
  76. private JMenuItem jMenuItem4;
  77. private JSeparator jSeparator1;
  78. private JMenuItem fitWindowMenuItem;
  79. private JMenuItem tileWindowMenuItem;
  80. private JSeparator jSeparator5;
  81. private JMenuItem consoleWindowMenuItem;
  82. private JMenuItem editorWindowMenuItem;
  83. private JMenuItem imageWindowMenuItem;
  84. private JMenu windowMenu;
  85. private JInternalFrame consoleFrame;
  86. private JInternalFrame editorFrame;
  87. private JInternalFrame imagePanelFrame;
  88. private JDesktopPane desktop;
  89. private JCheckBoxMenuItem smallTrianglesMenuItem;
  90. private JMenuItem textureCacheClearMenuItem;
  91. private JSeparator jSeparator4;
  92. private JMenuItem resetZoomMenuItem;
  93. private JMenu imageMenu;
  94. private ImagePanel imagePanel;
  95. private JPanel jPanel6;
  96. private JCheckBoxMenuItem clearLogMenuItem;
  97. private JPanel jPanel5;
  98. private JButton taskCancelButton;
  99. private JProgressBar taskProgressBar;
  100. private JSeparator jSeparator3;
  101. private JCheckBoxMenuItem autoBuildMenuItem;
  102. private JMenuItem iprMenuItem;
  103. private JMenuItem renderMenuItem;
  104. private JMenuItem buildMenuItem;
  105. private JMenu sceneMenu;
  106. private JTextArea editorTextArea;
  107. private JTextArea consoleTextArea;
  108. private JButton clearConsoleButton;
  109. private JPanel jPanel4;
  110. private JScrollPane jScrollPane2;
  111. private JButton iprButton;
  112. private JButton buildButton;
  113. private JMenuItem saveAsMenuItem;
  114. private JMenuItem saveMenuItem;
  115. private JMenuItem openFileMenuItem;
  116. private JMenuItem newFileMenuItem;
  117. private JMenu fileMenu;
  118. private JMenuBar jMenuBar1;
  119. // non-swing items
  120. private String currentFile;
  121. private String currentTask;
  122. private int currentTaskLastP;
  123. private SunflowAPI api;
  124. public static void usage(boolean verbose) {
  125. System.out.println("Usage: SunflowGUI [options] scenefile");
  126. if (verbose) {
  127. System.out.println("Sunflow v" + SunflowAPI.VERSION + " textmode");
  128. System.out.println("Renders the specified scene file");
  129. System.out.println("Options:");
  130. System.out.println(" -o filename Saves the output as the specified filename (png, hdr, tga)");
  131. System.out.println(" #'s get expanded to the current frame number");
  132. System.out.println(" -nogui Don't open the frame showing rendering progress");
  133. System.out.println(" -ipr Render using progressive algorithm");
  134. System.out.println(" -sampler type Render using the specified algorithm");
  135. System.out.println(" -threads n Render using n threads");
  136. System.out.println(" -lopri Set thread priority to low (default)");
  137. System.out.println(" -hipri Set thread priority to high");
  138. System.out.println(" -smallmesh Load triangle meshes using triangles optimized for memory use");
  139. System.out.println(" -dumpkd Dump KDTree to an obj file for visualization");
  140. System.out.println(" -buildonly Do not call render method after loading the scene");
  141. System.out.println(" -showaa Display sampling levels per pixel for bucket renderer");
  142. System.out.println(" -nogi Disable any global illumination engines in the scene");
  143. System.out.println(" -nocaustics Disable any caustic engine in the scene");
  144. System.out.println(" -pathgi n Use path tracing with n samples to render global illumination");
  145. System.out.println(" -quick_ambocc d Applies ambient occlusion to the scene with specified maximum distance");
  146. System.out.println(" -quick_uvs Applies a surface uv visualization shader to the scene");
  147. System.out.println(" -quick_normals Applies a surface normal visualization shader to the scene");
  148. System.out.println(" -quick_id Renders using a unique color for each instance");
  149. System.out.println(" -quick_prims Renders using a unique color for each primitive");
  150. System.out.println(" -quick_gray Renders using a plain gray diffuse shader");
  151. System.out.println(" -quick_wire Renders using a wireframe shader");
  152. System.out.println(" -resolution w h Changes the render resolution to the specified width and height (in pixels)");
  153. System.out.println(" -aa min max Overrides the image anti-aliasing depths");
  154. System.out.println(" -bucket n order Changes the default bucket size to n pixels and the default order");
  155. System.out.println(" -bake name Bakes a lightmap for the specified instance");
  156. System.out.println(" -bakedir dir Selects the type of lightmap baking: dir=view or ortho");
  157. System.out.println(" -filter type Selects the image filter to use");
  158. System.out.println(" -bench Run several built-in scenes for benchmark purposes");
  159. System.out.println(" -rtbench Run realtime ray-tracing benchmark");
  160. System.out.println(" -frame n Set frame number to the specified value");
  161. System.out.println(" -anim n1 n2 Render all frames between the two specified values (inclusive)");
  162. System.out.println(" -v verbosity Set the verbosity level: 0=none,1=errors,2=warnings,3=info,4=detailed");
  163. System.out.println(" -h Prints this message");
  164. }
  165. System.exit(1);
  166. }
  167. public static void main(String[] args) {
  168. if (args.length > 0) {
  169. boolean showFrame = true;
  170. String sampler = "bucket";
  171. boolean noRender = false;
  172. String filename = null;
  173. String input = null;
  174. int i = 0;
  175. int threads = 0;
  176. boolean lowPriority = true;
  177. boolean showAA = false;
  178. boolean noGI = false;
  179. boolean noCaustics = false;
  180. int pathGI = 0;
  181. Shader shaderOverride = null;
  182. int resolutionW = 0, resolutionH = 0;
  183. int aaMin = -5, aaMax = -5;
  184. int bucketSize = 0;
  185. String bucketOrder = null;
  186. String bakingName = null;
  187. boolean bakeViewdep = false;
  188. String filterType = null;
  189. boolean runBenchmark = false;
  190. boolean runRTBenchmark = false;
  191. int frameStart = 1, frameStop = 1;
  192. while (i < args.length) {
  193. if (args[i].equals("-o")) {
  194. if (i > args.length - 2)
  195. usage(false);
  196. filename = args[i + 1];
  197. i += 2;
  198. } else if (args[i].equals("-nogui")) {
  199. showFrame = false;
  200. i++;
  201. } else if (args[i].equals("-ipr")) {
  202. sampler = "ipr";
  203. i++;
  204. } else if (args[i].equals("-threads")) {
  205. if (i > args.length - 2)
  206. usage(false);
  207. threads = Integer.parseInt(args[i + 1]);
  208. i += 2;
  209. } else if (args[i].equals("-lopri")) {
  210. lowPriority = true;
  211. i++;
  212. } else if (args[i].equals("-hipri")) {
  213. lowPriority = false;
  214. i++;
  215. } else if (args[i].equals("-sampler")) {
  216. if (i > args.length - 2)
  217. usage(false);
  218. sampler = args[i + 1];
  219. i += 2;
  220. } else if (args[i].equals("-smallmesh")) {
  221. TriangleMesh.setSmallTriangles(true);
  222. i++;
  223. } else if (args[i].equals("-dumpkd")) {
  224. KDTree.setDumpMode(true, "kdtree");
  225. i++;
  226. } else if (args[i].equals("-buildonly")) {
  227. noRender = true;
  228. i++;
  229. } else if (args[i].equals("-showaa")) {
  230. showAA = true;
  231. i++;
  232. } else if (args[i].equals("-nogi")) {
  233. noGI = true;
  234. i++;
  235. } else if (args[i].equals("-nocaustics")) {
  236. noCaustics = true;
  237. i++;
  238. } else if (args[i].equals("-pathgi")) {
  239. if (i > args.length - 2)
  240. usage(false);
  241. pathGI = Integer.parseInt(args[i + 1]);
  242. i += 2;
  243. } else if (args[i].equals("-quick_ambocc")) {
  244. if (i > args.length - 2)
  245. usage(false);
  246. float d = Float.parseFloat(args[i + 1]);
  247. shaderOverride = new AmbientOcclusionShader(Color.WHITE, d);
  248. i += 2;
  249. } else if (args[i].equals("-quick_uvs")) {
  250. if (i > args.length - 1)
  251. usage(false);
  252. shaderOverride = new UVShader();
  253. i++;
  254. } else if (args[i].equals("-quick_normals")) {
  255. if (i > args.length - 1)
  256. usage(false);
  257. shaderOverride = new NormalShader();
  258. i++;
  259. } else if (args[i].equals("-quick_id")) {
  260. if (i > args.length - 1)
  261. usage(false);
  262. shaderOverride = new IDShader();
  263. i++;
  264. } else if (args[i].equals("-quick_prims")) {
  265. if (i > args.length - 1)
  266. usage(false);
  267. shaderOverride = new PrimIDShader();
  268. i++;
  269. } else if (args[i].equals("-quick_gray")) {
  270. if (i > args.length - 1)
  271. usage(false);
  272. shaderOverride = new QuickGrayShader();
  273. i++;
  274. } else if (args[i].equals("-quick_wire")) {
  275. if (i > args.length - 1)
  276. usage(false);
  277. shaderOverride = new WireframeShader();
  278. i++;
  279. } else if (args[i].equals("-resolution")) {
  280. if (i > args.length - 3)
  281. usage(false);
  282. resolutionW = Integer.parseInt(args[i + 1]);
  283. resolutionH = Integer.parseInt(args[i + 2]);
  284. i += 3;
  285. } else if (args[i].equals("-aa")) {
  286. if (i > args.length - 3)
  287. usage(false);
  288. aaMin = Integer.parseInt(args[i + 1]);
  289. aaMax = Integer.parseInt(args[i + 2]);
  290. i += 3;
  291. } else if (args[i].equals("-bucket")) {
  292. if (i > args.length - 3)
  293. usage(false);
  294. bucketSize = Integer.parseInt(args[i + 1]);
  295. bucketOrder = args[i + 2];
  296. i += 3;
  297. } else if (args[i].equals("-bake")) {
  298. if (i > args.length - 2)
  299. usage(false);
  300. bakingName = args[i + 1];
  301. i += 2;
  302. } else if (args[i].equals("-bakedir")) {
  303. if (i > args.length - 2)
  304. usage(false);
  305. String baketype = args[i + 1];
  306. if (baketype.equals("view"))
  307. bakeViewdep = true;
  308. else if (baketype.equals("ortho"))
  309. bakeViewdep = false;
  310. else
  311. usage(false);
  312. i += 2;
  313. } else if (args[i].equals("-filter")) {
  314. if (i > args.length - 2)
  315. usage(false);
  316. filterType = args[i + 1];
  317. i += 2;
  318. } else if (args[i].equals("-bench")) {
  319. runBenchmark = true;
  320. i++;
  321. } else if (args[i].equals("-rtbench")) {
  322. runRTBenchmark = true;
  323. i++;
  324. } else if (args[i].equals("-frame")) {
  325. if (i > args.length - 2)
  326. usage(false);
  327. frameStart = frameStop = Integer.parseInt(args[i + 1]);
  328. i += 2;
  329. } else if (args[i].equals("-anim")) {
  330. if (i > args.length - 3)
  331. usage(false);
  332. frameStart = Integer.parseInt(args[i + 1]);
  333. frameStop = Integer.parseInt(args[i + 2]);
  334. i += 3;
  335. } else if (args[i].equals("-v")) {
  336. if (i > args.length - 2)
  337. usage(false);
  338. UI.verbosity(Integer.parseInt(args[i + 1]));
  339. i += 2;
  340. } else if (args[i].equals("-h") || args[i].equals("-help")) {
  341. usage(true);
  342. } else {
  343. if (input != null)
  344. usage(false);
  345. input = args[i];
  346. i++;
  347. }
  348. }
  349. if (runBenchmark) {
  350. SunflowAPI.runSystemCheck();
  351. new Benchmark().execute();
  352. return;
  353. }
  354. if (runRTBenchmark) {
  355. SunflowAPI.runSystemCheck();
  356. new RealtimeBenchmark(showFrame, threads);
  357. return;
  358. }
  359. if (input == null)
  360. usage(false);
  361. SunflowAPI.runSystemCheck();
  362. if (frameStart < frameStop && showFrame) {
  363. UI.printWarning(Module.GUI, "Animations should not be rendered without -nogui - forcing GUI off anyway");
  364. showFrame = false;
  365. }
  366. if (frameStart < frameStop && filename == null) {
  367. filename = "output.#.png";
  368. UI.printWarning(Module.GUI, "Animation output was not specified - defaulting to: \"%s\"", filename);
  369. }
  370. for (int frameNumber = frameStart; frameNumber <= frameStop; frameNumber++) {
  371. SunflowAPI api = SunflowAPI.create(input, frameNumber);
  372. if (api == null)
  373. continue;
  374. if (noRender)
  375. continue;
  376. if (resolutionW > 0 && resolutionH > 0) {
  377. api.parameter("resolutionX", resolutionW);
  378. api.parameter("resolutionY", resolutionH);
  379. }
  380. if (aaMin != -5 || aaMax != -5) {
  381. api.parameter("aa.min", aaMin);
  382. api.parameter("aa.max", aaMax);
  383. }
  384. if (bucketSize > 0)
  385. api.parameter("bucket.size", bucketSize);
  386. if (bucketOrder != null)
  387. api.parameter("bucket.order", bucketOrder);
  388. api.parameter("aa.display", showAA);
  389. api.parameter("threads", threads);
  390. api.parameter("threads.lowPriority", lowPriority);
  391. if (bakingName != null) {
  392. api.parameter("baking.instance", bakingName);
  393. api.parameter("baking.viewdep", bakeViewdep);
  394. }
  395. if (filterType != null)
  396. api.parameter("filter", filterType);
  397. if (noGI)
  398. api.parameter("gi.engine", "none");
  399. else if (pathGI > 0) {
  400. api.parameter("gi.engine", "path");
  401. api.parameter("gi.path.samples", pathGI);
  402. }
  403. if (noCaustics)
  404. api.parameter("caustics", "none");
  405. api.parameter("sampler", sampler);
  406. api.options(SunflowAPI.DEFAULT_OPTIONS);
  407. if (shaderOverride != null) {
  408. api.shader("ambocc", shaderOverride);
  409. api.shaderOverride("ambocc", true);
  410. }
  411. // create display
  412. Display display;
  413. String currentFilename = (filename != null) ? filename.replace("#", String.format("%04d", frameNumber)) : null;
  414. if (showFrame) {
  415. display = new FrameDisplay(currentFilename);
  416. } else {
  417. if (currentFilename != null && currentFilename.endsWith(".exr")) {
  418. try {
  419. display = new OpenExrDisplay(currentFilename, "zip", "float");
  420. } catch (Exception e) {
  421. e.printStackTrace();
  422. return;
  423. }
  424. } else if (currentFilename != null && currentFilename.equals("imgpipe")) {
  425. display = new ImgPipeDisplay();
  426. } else
  427. display = new FileDisplay(currentFilename);
  428. }
  429. api.render(SunflowAPI.DEFAULT_OPTIONS, display);
  430. }
  431. } else {
  432. MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
  433. SunflowGUI gui = new SunflowGUI();
  434. gui.setVisible(true);
  435. Dimension screenRes = Toolkit.getDefaultToolkit().getScreenSize();
  436. if (screenRes.getWidth() <= DEFAULT_WIDTH || screenRes.getHeight() <= DEFAULT_HEIGHT)
  437. gui.setExtendedState(MAXIMIZED_BOTH);
  438. gui.tileWindowMenuItem.doClick();
  439. SunflowAPI.runSystemCheck();
  440. }
  441. }
  442. public SunflowGUI() {
  443. super();
  444. currentFile = null;
  445. api = null;
  446. initGUI();
  447. pack();
  448. setLocationRelativeTo(null);
  449. newFileMenuItemActionPerformed(null);
  450. UI.set(this);
  451. }
  452. private void initGUI() {
  453. setTitle("Sunflow v" + SunflowAPI.VERSION);
  454. setDefaultCloseOperation(EXIT_ON_CLOSE);
  455. {
  456. desktop = new JDesktopPane();
  457. getContentPane().add(desktop, BorderLayout.CENTER);
  458. Dimension screenRes = Toolkit.getDefaultToolkit().getScreenSize();
  459. if (screenRes.getWidth() <= DEFAULT_WIDTH || screenRes.getHeight() <= DEFAULT_HEIGHT)
  460. desktop.setPreferredSize(new java.awt.Dimension(640, 480));
  461. else
  462. desktop.setPreferredSize(new java.awt.Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT));
  463. {
  464. imagePanelFrame = new JInternalFrame();
  465. desktop.add(imagePanelFrame);
  466. {
  467. jPanel1 = new JPanel();
  468. FlowLayout jPanel1Layout = new FlowLayout();
  469. jPanel1Layout.setAlignment(FlowLayout.LEFT);
  470. jPanel1.setLayout(jPanel1Layout);
  471. imagePanelFrame.getContentPane().add(jPanel1, BorderLayout.NORTH);
  472. {
  473. renderButton = new JButton();
  474. jPanel1.add(renderButton);
  475. renderButton.setText("Render");
  476. renderButton.addActionListener(new ActionListener() {
  477. public void actionPerformed(ActionEvent evt) {
  478. renderMenuItemActionPerformed(evt);
  479. }
  480. });
  481. }
  482. {
  483. iprButton = new JButton();
  484. jPanel1.add(iprButton);
  485. iprButton.setText("IPR");
  486. iprButton.addActionListener(new ActionListener() {
  487. public void actionPerformed(ActionEvent evt) {
  488. iprMenuItemActionPerformed(evt);
  489. }
  490. });
  491. }
  492. }
  493. {
  494. imagePanel = new ImagePanel();
  495. imagePanelFrame.getContentPane().add(imagePanel, BorderLayout.CENTER);
  496. }
  497. imagePanelFrame.pack();
  498. imagePanelFrame.setResizable(true);
  499. imagePanelFrame.setMaximizable(true);
  500. imagePanelFrame.setVisible(true);
  501. imagePanelFrame.setTitle("Image");
  502. imagePanelFrame.setIconifiable(true);
  503. }
  504. {
  505. editorFrame = new JInternalFrame();
  506. desktop.add(editorFrame);
  507. editorFrame.setTitle("Script Editor");
  508. editorFrame.setMaximizable(true);
  509. editorFrame.setResizable(true);
  510. editorFrame.setIconifiable(true);
  511. {
  512. jScrollPane1 = new JScrollPane();
  513. editorFrame.getContentPane().add(jScrollPane1, BorderLayout.CENTER);
  514. jScrollPane1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
  515. jScrollPane1.setPreferredSize(new java.awt.Dimension(360, 280));
  516. {
  517. editorTextArea = new JTextArea();
  518. jScrollPane1.setViewportView(editorTextArea);
  519. editorTextArea.setFont(new java.awt.Font("Monospaced", 0, 12));
  520. // drag and drop
  521. editorTextArea.setTransferHandler(new SceneTransferHandler());
  522. }
  523. }
  524. {
  525. jPanel3 = new JPanel();
  526. editorFrame.getContentPane().add(jPanel3, BorderLayout.SOUTH);
  527. FlowLayout jPanel3Layout = new FlowLayout();
  528. jPanel3Layout.setAlignment(FlowLayout.RIGHT);
  529. jPanel3.setLayout(jPanel3Layout);
  530. {
  531. buildButton = new JButton();
  532. jPanel3.add(buildButton);
  533. buildButton.setText("Build Scene");
  534. buildButton.addActionListener(new ActionListener() {
  535. public void actionPerformed(ActionEvent evt) {
  536. buildMenuItemActionPerformed(evt);
  537. }
  538. });
  539. }
  540. }
  541. editorFrame.pack();
  542. editorFrame.setVisible(true);
  543. }
  544. {
  545. consoleFrame = new JInternalFrame();
  546. desktop.add(consoleFrame);
  547. consoleFrame.setIconifiable(true);
  548. consoleFrame.setMaximizable(true);
  549. consoleFrame.setResizable(true);
  550. consoleFrame.setTitle("Console");
  551. {
  552. jScrollPane2 = new JScrollPane();
  553. consoleFrame.getContentPane().add(jScrollPane2, BorderLayout.CENTER);
  554. jScrollPane2.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
  555. jScrollPane2.setPreferredSize(new java.awt.Dimension(360, 100));
  556. {
  557. consoleTextArea = new JTextArea();
  558. jScrollPane2.setViewportView(consoleTextArea);
  559. consoleTextArea.setFont(new java.awt.Font("Monospaced", 0, 12));
  560. consoleTextArea.setEditable(false);
  561. }
  562. }
  563. {
  564. jPanel4 = new JPanel();
  565. consoleFrame.getContentPane().add(jPanel4, BorderLayout.SOUTH);
  566. BorderLayout jPanel4Layout = new BorderLayout();
  567. jPanel4.setLayout(jPanel4Layout);
  568. {
  569. jPanel6 = new JPanel();
  570. BorderLayout jPanel6Layout = new BorderLayout();
  571. jPanel6.setLayout(jPanel6Layout);
  572. jPanel4.add(jPanel6, BorderLayout.CENTER);
  573. jPanel6.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0));
  574. {
  575. taskProgressBar = new JProgressBar();
  576. jPanel6.add(taskProgressBar);
  577. taskProgressBar.setEnabled(false);
  578. taskProgressBar.setString("");
  579. taskProgressBar.setStringPainted(true);
  580. taskProgressBar.setOpaque(false);
  581. }
  582. }
  583. {
  584. jPanel5 = new JPanel();
  585. FlowLayout jPanel5Layout = new FlowLayout();
  586. jPanel5Layout.setAlignment(FlowLayout.RIGHT);
  587. jPanel5.setLayout(jPanel5Layout);
  588. jPanel4.add(jPanel5, BorderLayout.EAST);
  589. {
  590. taskCancelButton = new JButton();
  591. jPanel5.add(taskCancelButton);
  592. taskCancelButton.setText("Cancel");
  593. taskCancelButton.setEnabled(false);
  594. taskCancelButton.addActionListener(new ActionListener() {
  595. public void actionPerformed(ActionEvent evt) {
  596. UI.taskCancel();
  597. }
  598. });
  599. }
  600. {
  601. clearConsoleButton = new JButton();
  602. jPanel5.add(clearConsoleButton);
  603. clearConsoleButton.setText("Clear");
  604. clearConsoleButton.addActionListener(new ActionListener() {
  605. public void actionPerformed(ActionEvent evt) {
  606. clearConsole();
  607. }
  608. });
  609. }
  610. }
  611. }
  612. consoleFrame.pack();
  613. consoleFrame.setVisible(true);
  614. }
  615. }
  616. {
  617. jMenuBar1 = new JMenuBar();
  618. setJMenuBar(jMenuBar1);
  619. {
  620. fileMenu = new JMenu();
  621. jMenuBar1.add(fileMenu);
  622. fileMenu.setText("File");
  623. {
  624. newFileMenuItem = new JMenuItem();
  625. fileMenu.add(newFileMenuItem);
  626. newFileMenuItem.setText("New");
  627. newFileMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl N"));
  628. newFileMenuItem.addActionListener(new ActionListener() {
  629. public void actionPerformed(ActionEvent evt) {
  630. newFileMenuItemActionPerformed(evt);
  631. }
  632. });
  633. }
  634. {
  635. openFileMenuItem = new JMenuItem();
  636. fileMenu.add(openFileMenuItem);
  637. openFileMenuItem.setText("Open ...");
  638. openFileMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl O"));
  639. openFileMenuItem.addActionListener(new ActionListener() {
  640. public void actionPerformed(ActionEvent evt) {
  641. openFileMenuItemActionPerformed(evt);
  642. }
  643. });
  644. }
  645. {
  646. saveMenuItem = new JMenuItem();
  647. fileMenu.add(saveMenuItem);
  648. saveMenuItem.setText("Save");
  649. saveMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl S"));
  650. saveMenuItem.addActionListener(new ActionListener() {
  651. public void actionPerformed(ActionEvent evt) {
  652. saveCurrentFile(currentFile);
  653. }
  654. });
  655. }
  656. {
  657. saveAsMenuItem = new JMenuItem();
  658. fileMenu.add(saveAsMenuItem);
  659. saveAsMenuItem.setText("Save As ...");
  660. saveAsMenuItem.addActionListener(new ActionListener() {
  661. public void actionPerformed(ActionEvent evt) {
  662. saveAsMenuItemActionPerformed(evt);
  663. }
  664. });
  665. }
  666. {
  667. jSeparator2 = new JSeparator();
  668. fileMenu.add(jSeparator2);
  669. }
  670. {
  671. exitMenuItem = new JMenuItem();
  672. fileMenu.add(exitMenuItem);
  673. exitMenuItem.setText("Exit");
  674. exitMenuItem.addActionListener(new ActionListener() {
  675. public void actionPerformed(ActionEvent evt) {
  676. System.exit(0);
  677. }
  678. });
  679. }
  680. }
  681. {
  682. sceneMenu = new JMenu();
  683. jMenuBar1.add(sceneMenu);
  684. sceneMenu.setText("Scene");
  685. {
  686. buildMenuItem = new JMenuItem();
  687. sceneMenu.add(buildMenuItem);
  688. buildMenuItem.setText("Build");
  689. buildMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl B"));
  690. buildMenuItem.addActionListener(new ActionListener() {
  691. public void actionPerformed(ActionEvent evt) {
  692. if (sceneMenu.isEnabled())
  693. buildMenuItemActionPerformed(evt);
  694. }
  695. });
  696. }
  697. {
  698. autoBuildMenuItem = new JCheckBoxMenuItem();
  699. sceneMenu.add(autoBuildMenuItem);
  700. autoBuildMenuItem.setText("Build on open");
  701. autoBuildMenuItem.setSelected(true);
  702. }
  703. {
  704. jSeparator3 = new JSeparator();
  705. sceneMenu.add(jSeparator3);
  706. }
  707. {
  708. renderMenuItem = new JMenuItem();
  709. sceneMenu.add(renderMenuItem);
  710. renderMenuItem.setText("Render");
  711. renderMenuItem.addActionListener(new ActionListener() {
  712. public void actionPerformed(ActionEvent evt) {
  713. renderMenuItemActionPerformed(evt);
  714. }
  715. });
  716. }
  717. {
  718. iprMenuItem = new JMenuItem();
  719. sceneMenu.add(iprMenuItem);
  720. iprMenuItem.setText("IPR");
  721. iprMenuItem.addActionListener(new ActionListener() {
  722. public void actionPerformed(ActionEvent evt) {
  723. iprMenuItemActionPerformed(evt);
  724. }
  725. });
  726. }
  727. {
  728. clearLogMenuItem = new JCheckBoxMenuItem();
  729. sceneMenu.add(clearLogMenuItem);
  730. clearLogMenuItem.setText("Auto Clear Log");
  731. clearLogMenuItem.setToolTipText("Clears the console before building or rendering");
  732. clearLogMenuItem.setSelected(true);
  733. }
  734. {
  735. jSeparator4 = new JSeparator();
  736. sceneMenu.add(jSeparator4);
  737. }
  738. {
  739. textureCacheClearMenuItem = new JMenuItem();
  740. sceneMenu.add(textureCacheClearMenuItem);
  741. textureCacheClearMenuItem.setText("Clear Texture Cache");
  742. textureCacheClearMenuItem.addActionListener(new ActionListener() {
  743. public void actionPerformed(ActionEvent evt) {
  744. textureCacheClearMenuItemActionPerformed(evt);
  745. }
  746. });
  747. }
  748. {
  749. smallTrianglesMenuItem = new JCheckBoxMenuItem();
  750. sceneMenu.add(smallTrianglesMenuItem);
  751. smallTrianglesMenuItem.setText("Low Mem Triangles");
  752. smallTrianglesMenuItem.setToolTipText("Load future meshes using a low memory footprint triangle representation");
  753. smallTrianglesMenuItem.addActionListener(new ActionListener() {
  754. public void actionPerformed(ActionEvent evt) {
  755. smallTrianglesMenuItemActionPerformed(evt);
  756. }
  757. });
  758. }
  759. }
  760. {
  761. imageMenu = new JMenu();
  762. jMenuBar1.add(imageMenu);
  763. imageMenu.setText("Image");
  764. {
  765. resetZoomMenuItem = new JMenuItem();
  766. imageMenu.add(resetZoomMenuItem);
  767. resetZoomMenuItem.setText("Reset Zoom");
  768. resetZoomMenuItem.addActionListener(new ActionListener() {
  769. public void actionPerformed(ActionEvent evt) {
  770. imagePanel.reset();
  771. }
  772. });
  773. }
  774. {
  775. fitWindowMenuItem = new JMenuItem();
  776. imageMenu.add(fitWindowMenuItem);
  777. fitWindowMenuItem.setText("Fit to Window");
  778. fitWindowMenuItem.addActionListener(new ActionListener() {
  779. public void actionPerformed(ActionEvent evt) {
  780. imagePanel.fit();
  781. }
  782. });
  783. }
  784. {
  785. jSeparator1 = new JSeparator();
  786. imageMenu.add(jSeparator1);
  787. }
  788. {
  789. jMenuItem4 = new JMenuItem();
  790. imageMenu.add(jMenuItem4);
  791. jMenuItem4.setText("Save Image ...");
  792. jMenuItem4.addActionListener(new ActionListener() {
  793. public void actionPerformed(ActionEvent evt) {
  794. // imagePanel.image;
  795. JFileChooser fc = new JFileChooser(".");
  796. fc.setFileFilter(new FileFilter() {
  797. @Override
  798. public String getDescription() {
  799. return "Image File";
  800. }
  801. @Override
  802. public boolean accept(File f) {
  803. return (f.isDirectory() || f.getName().endsWith(".png") || f.getName().endsWith(".tga"));
  804. }
  805. });
  806. if (fc.showSaveDialog(SunflowGUI.this) == JFileChooser.APPROVE_OPTION) {
  807. String filename = fc.getSelectedFile().getAbsolutePath();
  808. imagePanel.save(filename);
  809. }
  810. }
  811. });
  812. }
  813. }
  814. {
  815. windowMenu = new JMenu();
  816. jMenuBar1.add(windowMenu);
  817. windowMenu.setText("Window");
  818. }
  819. {
  820. imageWindowMenuItem = new JMenuItem();
  821. windowMenu.add(imageWindowMenuItem);
  822. imageWindowMenuItem.setText("Image");
  823. imageWindowMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 1"));
  824. imageWindowMenuItem.addActionListener(new ActionListener() {
  825. public void actionPerformed(ActionEvent evt) {
  826. selectFrame(imagePanelFrame);
  827. }
  828. });
  829. }
  830. {
  831. editorWindowMenuItem = new JMenuItem();
  832. windowMenu.add(editorWindowMenuItem);
  833. editorWindowMenuItem.setText("Script Editor");
  834. editorWindowMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 2"));
  835. editorWindowMenuItem.addActionListener(new ActionListener() {
  836. public void actionPerformed(ActionEvent evt) {
  837. selectFrame(editorFrame);
  838. }
  839. });
  840. }
  841. {
  842. consoleWindowMenuItem = new JMenuItem();
  843. windowMenu.add(consoleWindowMenuItem);
  844. consoleWindowMenuItem.setText("Console");
  845. consoleWindowMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl 3"));
  846. consoleWindowMenuItem.addActionListener(new ActionListener() {
  847. public void actionPerformed(ActionEvent evt) {
  848. selectFrame(consoleFrame);
  849. }
  850. });
  851. }
  852. {
  853. jSeparator5 = new JSeparator();
  854. windowMenu.add(jSeparator5);
  855. }
  856. {
  857. tileWindowMenuItem = new JMenuItem();
  858. windowMenu.add(tileWindowMenuItem);
  859. tileWindowMenuItem.setText("Tile");
  860. tileWindowMenuItem.setAccelerator(KeyStroke.getKeyStroke("ctrl T"));
  861. tileWindowMenuItem.addActionListener(new ActionListener() {
  862. public void actionPerformed(ActionEvent evt) {
  863. tileWindowMenuItemActionPerformed(evt);
  864. }
  865. });
  866. }
  867. }
  868. }
  869. private void newFileMenuItemActionPerformed(ActionEvent evt) {
  870. if (evt != null) {
  871. // check save?
  872. }
  873. // put some template code into the editor
  874. String template = "import org.sunflow.core.*;\nimport org.sunflow.core.accel.*;\nimport org.sunflow.core.camera.*;\nimport org.sunflow.core.primitive.*;\nimport org.sunflow.core.shader.*;\nimport org.sunflow.image.Color;\nimport org.sunflow.math.*;\n\npublic void build() {\n // your code goes here\n\n}\n";
  875. editorTextArea.setText(template);
  876. }
  877. private void openFileMenuItemActionPerformed(ActionEvent evt) {
  878. JFileChooser fc = new JFileChooser(".");
  879. fc.setFileFilter(new FileFilter() {
  880. @Override
  881. public String getDescription() {
  882. return "Scene File";
  883. }
  884. @Override
  885. public boolean accept(File f) {
  886. return (f.isDirectory() || f.getName().endsWith(".sc") || f.getName().endsWith(".java"));
  887. }
  888. });
  889. if (fc.showOpenDialog(SunflowGUI.this) == JFileChooser.APPROVE_OPTION) {
  890. final String f = fc.getSelectedFile().getAbsolutePath();
  891. openFile(f);
  892. }
  893. }
  894. private void buildMenuItemActionPerformed(ActionEvent evt) {
  895. new Thread() {
  896. public void run() {
  897. setEnableInterface(false);
  898. if (clearLogMenuItem.isSelected())
  899. clearConsole();
  900. Timer t = new Timer();
  901. t.start();
  902. try {
  903. api = SunflowAPI.compile(editorTextArea.getText());
  904. } catch (NoClassDefFoundError e) {
  905. UI.printError(Module.GUI, "Janino library not found. Please check command line.");
  906. api = null;
  907. }
  908. if (api != null) {
  909. try {
  910. if (currentFile != null) {
  911. String dir = new File(currentFile).getAbsoluteFile().getParent();
  912. api.addIncludeSearchPath(dir);
  913. api.addIncludeSearchPath(dir);
  914. }
  915. api.build();
  916. } catch (Exception e) {
  917. UI.printError(Module.GUI, "Build terminated abnormally: %s", e.getMessage());
  918. for (StackTraceElement elt : e.getStackTrace()) {
  919. UI.printInfo(Module.GUI, " at %s", elt.toString());
  920. }
  921. e.printStackTrace();
  922. }
  923. t.end();
  924. UI.printInfo(Module.GUI, "Build time: %s", t.toString());
  925. }
  926. setEnableInterface(true);
  927. }
  928. }.start();
  929. }
  930. private void clearConsole() {
  931. consoleTextArea.setText(null);
  932. }
  933. private void println(final String s) {
  934. SwingUtilities.invokeLater(new Runnable() {
  935. public void run() {
  936. consoleTextArea.append(s + "\n");
  937. }
  938. });
  939. }
  940. private void setEnableInterface(boolean enabled) {
  941. // lock or unlock options which are unsafe during builds or renders
  942. newFileMenuItem.setEnabled(enabled);
  943. openFileMenuItem.setEnabled(enabled);
  944. saveMenuItem.setEnabled(enabled);
  945. saveAsMenuItem.setEnabled(enabled);
  946. sceneMenu.setEnabled(enabled);
  947. buildButton.setEnabled(enabled);
  948. renderButton.setEnabled(enabled);
  949. iprButton.setEnabled(enabled);
  950. }
  951. public void print(Module m, PrintLevel level, String s) {
  952. if (level == PrintLevel.ERROR)
  953. JOptionPane.showMessageDialog(SunflowGUI.this, s, String.format("Error - %s", m.name()), JOptionPane.ERROR_MESSAGE);
  954. println(UI.formatOutput(m, level, s));
  955. }
  956. public void taskStart(String s, int min, int max) {
  957. currentTask = s;
  958. currentTaskLastP = -1;
  959. final int taskMin = min;
  960. final int taskMax = max;
  961. SwingUtilities.invokeLater(new Runnable() {
  962. public void run() {
  963. taskProgressBar.setEnabled(true);
  964. taskCancelButton.setEnabled(true);
  965. taskProgressBar.setMinimum(taskMin);
  966. taskProgressBar.setMaximum(taskMax);
  967. taskProgressBar.setValue(taskMin);
  968. taskProgressBar.setString(currentTask);
  969. }
  970. });
  971. }
  972. public void taskUpdate(int current) {
  973. final int taskCurrent = current;
  974. final String taskString = currentTask;
  975. SwingUtilities.invokeLater(new Runnable() {
  976. public void run() {
  977. taskProgressBar.setValue(taskCurrent);
  978. int p = (int) (100.0 * taskProgressBar.getPercentComplete());
  979. if (p > currentTaskLastP) {
  980. taskProgressBar.setString(taskString + " [" + p + "%]");
  981. currentTaskLastP = p;
  982. }
  983. }
  984. });
  985. }
  986. public void taskStop() {
  987. SwingUtilities.invokeLater(new Runnable() {
  988. public void run() {
  989. taskProgressBar.setValue(taskProgressBar.getMinimum());
  990. taskProgressBar.setString("");
  991. taskProgressBar.setEnabled(false);
  992. taskCancelButton.setEnabled(false);
  993. }
  994. });
  995. }
  996. private void renderMenuItemActionPerformed(ActionEvent evt) {
  997. new Thread() {
  998. public void run() {
  999. setEnableInterface(false);
  1000. if (clearLogMenuItem.isSelected())
  1001. clearConsole();
  1002. if (api != null) {
  1003. api.parameter("sampler", "bucket");
  1004. api.options(SunflowAPI.DEFAULT_OPTIONS);
  1005. api.render(SunflowAPI.DEFAULT_OPTIONS, imagePanel);
  1006. } else
  1007. UI.printError(Module.GUI, "Nothing to render!");
  1008. setEnableInterface(true);
  1009. }
  1010. }.start();
  1011. }
  1012. private void iprMenuItemActionPerformed(ActionEvent evt) {
  1013. new Thread() {
  1014. public void run() {
  1015. setEnableInterface(false);
  1016. if (clearLogMenuItem.isSelected())
  1017. clearConsole();
  1018. if (api != null) {
  1019. api.parameter("sampler", "ipr");
  1020. api.options(SunflowAPI.DEFAULT_OPTIONS);
  1021. api.render(SunflowAPI.DEFAULT_OPTIONS, imagePanel);
  1022. } else
  1023. UI.printError(Module.GUI, "Nothing to IPR!");
  1024. setEnableInterface(true);
  1025. }
  1026. }.start();
  1027. }
  1028. private void textureCacheClearMenuItemActionPerformed(ActionEvent evt) {
  1029. TextureCache.flush();
  1030. }
  1031. private void smallTrianglesMenuItemActionPerformed(ActionEvent evt) {
  1032. TriangleMesh.setSmallTriangles(smallTrianglesMenuItem.isSelected());
  1033. }
  1034. private void saveAsMenuItemActionPerformed(ActionEvent evt) {
  1035. JFileChooser fc = new JFileChooser(".");
  1036. fc.setFileFilter(new FileFilter() {
  1037. @Override
  1038. public String getDescription() {
  1039. return "Scene File";
  1040. }
  1041. @Override
  1042. public boolean accept(File f) {
  1043. return (f.isDirectory() || f.getName().endsWith(".java"));
  1044. }
  1045. });
  1046. if (fc.showSaveDialog(SunflowGUI.this) == JFileChooser.APPROVE_OPTION) {
  1047. String f = fc.getSelectedFile().getAbsolutePath();
  1048. if (!f.endsWith(".java"))
  1049. f += ".java";
  1050. File file = new File(f);
  1051. if (!file.exists() || JOptionPane.showConfirmDialog(SunflowGUI.this, "This file already exists.\nOverwrite?", "Warning", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
  1052. // save file
  1053. saveCurrentFile(f);
  1054. }
  1055. }
  1056. }
  1057. private void saveCurrentFile(String filename) {
  1058. if (filename == null) {
  1059. // no filename was picked, go to save as dialog
  1060. saveAsMenuItemActionPerformed(null);
  1061. return;
  1062. }
  1063. FileWriter file;
  1064. try {
  1065. file = new FileWriter(filename);
  1066. // get text from editor pane
  1067. file.write(editorTextArea.getText());
  1068. file.close();
  1069. // update current filename
  1070. currentFile = filename;
  1071. UI.printInfo(Module.GUI, "Saved current script to \"%s\"", filename);
  1072. } catch (IOException e) {
  1073. UI.printError(Module.GUI, "Unable to save: \"%s\"", filename);
  1074. e.printStackTrace();
  1075. }
  1076. }
  1077. private void selectFrame(JInternalFrame frame) {
  1078. try {
  1079. frame.setSelected(true);
  1080. frame.setIcon(false);
  1081. } catch (PropertyVetoException e) {
  1082. // this should never happen
  1083. e.printStackTrace();
  1084. }
  1085. }
  1086. private void tileWindowMenuItemActionPerformed(ActionEvent evt) {
  1087. try {
  1088. if (imagePanelFrame.isIcon())
  1089. imagePanelFrame.setIcon(false);
  1090. if (editorFrame.isIcon())
  1091. editorFrame.setIcon(false);
  1092. if (consoleFrame.isIcon())
  1093. consoleFrame.setIcon(false);
  1094. int width = desktop.getWidth();
  1095. int height = desktop.getHeight();
  1096. int widthLeft = width * 7 / 12;
  1097. int widthRight = wi

Large files files are truncated, but you can click here to view the full file