scene.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><title>jMonkeyEngine SDK&#8201;&#8212;&#8201;The Scene</title><link rel="stylesheet" href="./asciidoctor.css">
  2. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  3. <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/sdk/development/scene.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/sdk/development/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"><i class="fa fa-sort-down" aria-hidden="true"></i></div><h1>jMonkeyEngine SDK&#8201;&#8212;&#8201;The Scene</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#how-to-access-the-scene">How to access the Scene</a></li><li><a href="#listening-for-node-selection">Listening for Node selection</a></li><li><a href="#requesting-the-scene">Requesting the Scene</a></li><li><a href="#undo-redo-support">Undo/Redo support</a></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><p>To reduce system overhead the jMonkeyEngine SDK Core supplies one scene/jme3 application that is shared between plugins. Furthermore there&#8217;s the “SceneExplorer that shows a visual representation of the scenegraph and its objects properties across plugins.</p></div></div></div>
  4. <div class="sect1"><h2 id="how-to-access-the-scene">How to access the Scene</h2><div class="sectionbody"><div class="paragraph"><p>There are several ways for your plugin to interact with the Scene:</p></div>
  5. <div class="ulist"><ul><li><p>It listens for selected spatials / objects and offers options for those</p></li><li><p>It requests the whole scene for itself and loads/arranges the content in it (e.g. a terrain editor or model animation plugin).</p></li></ul></div></div></div>
  6. <div class="sect1"><h2 id="listening-for-node-selection">Listening for Node selection</h2><div class="sectionbody"><div class="paragraph"><p>In the jMonkeyEngine SDK, all objects are wrapped into NetBeans “Nodes (different thing than jme Nodes!). Such nodes can have properties and icons and can be displayed and selected in the jMonkeyEngine SDK UI. The SceneExplorer shows a tree of Nodes that wrap the Spatials of the current scene and allows manipulating their properties on selection. A jME “Spatial is wrapped by a “JmeSpatial node, for example. One advantage of these Nodes is that one can manipulate properties of Spatials directly from the AWT thread.</p></div>
  7. <div class="paragraph"><p>To listen to the current selection, implement org.openide.util.LookupListener and register like this:</p></div>
  8. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> <span class="directive">final</span> <span class="predefined-type">Result</span>&lt;JmeSpatial&gt; result;
  9. <span class="comment">//method to register the listener;</span>
  10. <span class="directive">private</span> <span class="type">void</span> registerListener(){
  11. result = <span class="predefined-type">Utilities</span>.actionsGlobalContext().lookupResult(JmeSpatial.class);
  12. result.addLookupListener(<span class="local-variable">this</span>);
  13. }
  14. <span class="comment">//implements org.openide.util.LookupListener (called from AWT thread)</span>
  15. <span class="directive">public</span> <span class="type">void</span> resultChanged(LookupEvent ev) {
  16. <span class="predefined-type">Collection</span>&lt;JmeSpatial&gt; items = (<span class="predefined-type">Collection</span>&lt;JmeSpatial&gt;) result.allInstances();
  17. <span class="keyword">for</span> (JmeSpatial jmeSpatial : items) {
  18. <span class="comment">//Using the JmeSpatials properties you can modify the spatial directly from the AWT thread:</span>
  19. jmeSpatial.getPropertySets()[<span class="integer">0</span>].setValue(<span class="string"><span class="delimiter">&quot;</span><span class="content">Local Translation</span><span class="delimiter">&quot;</span></span>, Vector3f.ZERO);
  20. <span class="keyword">return</span>;
  21. }
  22. }</code></pre></div></div>
  23. <div class="paragraph"><p>You can also access the “real spatial but since its part of the scenegraph you will have to modify it on that thread:</p></div>
  24. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="comment">//retrieve the &quot;real&quot; spatial class from the JmeNode</span>
  25. <span class="keyword">for</span> (JmeSpatial jmeSpatial : items) {
  26. <span class="comment">//the spatial is stored inside the JmeSpatials &quot;Lookup&quot;, a general container for Objects</span>
  27. <span class="directive">final</span> Spatial realSpatial = jmeSpatial.getLookup().lookup(Spatial.class);
  28. <span class="comment">//use a Callable to execute on the render thread:</span>
  29. SceneApplication.getApplication().enqueue(<span class="keyword">new</span> <span class="predefined-type">Callable</span>() {
  30. <span class="directive">public</span> <span class="predefined-type">Object</span> call() <span class="directive">throws</span> <span class="exception">Exception</span> {
  31. realSpatial.setLocalTranslation(Vector3f.ZERO);
  32. <span class="keyword">return</span> <span class="predefined-constant">null</span>;
  33. }
  34. });
  35. <span class="keyword">return</span>;
  36. }</code></pre></div></div></div></div>
  37. <div class="sect1"><h2 id="requesting-the-scene">Requesting the Scene</h2><div class="sectionbody"><div class="paragraph"><p>If your plugin wants to use the scene by itself, it first has to implement SceneListener and register at the scene and then send a SceneRequest to the SceneApplication. When the SceneRequest has been approved and the current Scene has been closed, the SceneListener (your class) is called with its own SceneRequest as a parameter. When another plugin sends a SceneRequest it is also reported to you and its a hint that your RootNode has been removed from the Scene and you are no longer in control of it. You could also hook into the SceneRequests of other plugins to see if/when they are activated to display add-on plugins for that plugin.</p></div>
  38. <div class="paragraph"><p>+
  39. The SceneRequest object has to contain several things. A thing that you must supply is a jme “Node wrapped into a “JmeNode object. This is your rootNode that you use to display and build your scene. As soon as you control the scene, you will have to control the camera etc. yourself.</p></div>
  40. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">com.jme3.scene.Node rootNode = <span class="keyword">new</span> com.jme3.scene.Node(<span class="string"><span class="delimiter">&quot;</span><span class="content">MyRootNode</span><span class="delimiter">&quot;</span></span>);
  41. <span class="directive">private</span> <span class="type">void</span> registerSceneListener(){
  42. SceneApplication.getApplication().addSceneListener(<span class="local-variable">this</span>);
  43. }
  44. <span class="directive">private</span> <span class="type">void</span> requestScene(){
  45. <span class="comment">//create a jmeNode from the rootNode using the NodeUtility</span>
  46. JmeNode jmeNode = NodeUtility.createNode(rootNode);
  47. <span class="comment">//create the scene request</span>
  48. SceneRequest request=<span class="keyword">new</span> SceneRequest(<span class="local-variable">this</span>, jmeNode, assetManager);
  49. <span class="comment">//request the scene</span>
  50. SceneApplication.getApplication().openScene(request);
  51. }
  52. <span class="comment">//implements SceneListener (called from AWT thread)</span>
  53. <span class="directive">public</span> <span class="type">void</span> sceneOpened(SceneRequest request){
  54. <span class="comment">//check if its our request</span>
  55. <span class="keyword">if</span> (request.getRequester() == <span class="local-variable">this</span>) {
  56. <span class="comment">//we now own the scene, any operations on the scene have to be done via Callables</span>
  57. }
  58. }
  59. <span class="directive">public</span> <span class="type">void</span> sceneClosed(SceneRequest request) {
  60. <span class="keyword">if</span> (request.getRequester() == <span class="local-variable">this</span>) {
  61. <span class="comment">//we have to close the scene, any operations on the scene have to be done via Callables</span>
  62. }
  63. }</code></pre></div></div></div></div>
  64. <div class="sect1"><h2 id="undo-redo-support">Undo/Redo support</h2><div class="sectionbody"><div class="paragraph"><p>The jMonkeyEngine SDK has a global undo/redo queue that activates the undo/redo buttons. To use it in your TopComponent, add the following method:</p></div>
  65. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="annotation">@Override</span>
  66. <span class="directive">public</span> UndoRedo getUndoRedo() {
  67. <span class="keyword">return</span> Lookup.getDefault().lookup(SceneUndoRedoManager.class);
  68. }</code></pre></div></div>
  69. <div class="paragraph"><p>To add a undo/redo event that modifies objects on the Scenegraph, theres a special version of AbstractUndoableEdit which executes the undo/redo calls on the scene thread. Simply implement that class and add it to the queue like this:</p></div>
  70. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(<span class="local-variable">this</span>, <span class="keyword">new</span> AbstractUndoableSceneEdit() {
  71. <span class="annotation">@Override</span>
  72. <span class="directive">public</span> <span class="type">void</span> sceneUndo() {
  73. <span class="comment">//undo stuff in scene here</span>
  74. }
  75. <span class="annotation">@Override</span>
  76. <span class="directive">public</span> <span class="type">void</span> sceneRedo() {
  77. <span class="comment">//redo stuff in scene here</span>
  78. }
  79. <span class="annotation">@Override</span>
  80. <span class="directive">public</span> <span class="type">void</span> awtUndo() {
  81. <span class="comment">//undo stuff on awt thread here (updating of visual nodes etc, called post scene edit)</span>
  82. }
  83. <span class="annotation">@Override</span>
  84. <span class="directive">public</span> <span class="type">void</span> awtRedo() {
  85. <span class="comment">//redo stuff on awt thread here</span>
  86. }
  87. });</code></pre></div></div>
  88. <div class="paragraph"><p>Note: Its important that you use the method addEdit(Object source, UndoableEdit edit);</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2017-10-25 21:59:24 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
  89. apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
  90. indexName: 'jmonkeyengine',
  91. inputSelector: '#doc-search',
  92. debug: false // Set debug to true if you want to inspect the dropdown
  93. });</script></body></html>