From eca1fae8bcb7c4f82be97e87b8e51c784eb14dbe Mon Sep 17 00:00:00 2001
From: "nor..67"
-In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code. Animated models must be created in an external mesh editor (for example, Blender).
+In 3D games, you do not only load static 3D models, you also want to be able to trigger animations in the model from the Java code.
-What is required for the model?
+
+JME3 only loads and plays animated models, it does not create them.
+
+What is required for an animated model? (See also: Animation terminology)
-More information: Animation
+Unless you download free models, or buy them from a 3D artist, you must create your animated models in an external mesh editor (for example, Blender) yourself.
-What is required in your java class?
+
+What is required in your JME3-based Java class?
-Create one
-A controller has several animation channels (
@@ -92,7 +117,7 @@ There often are situations where you want to run several animation sequences at
...
-To reset a controller, call
The following information is available for a channel.
@@ -219,7 +244,7 @@ The following information is available for a channel.
Use the following methods to add or remove individual bones to an AnimChannel. This is useful when you play two animations in parallel on two channels, and each controls a subset of the bones (e.g. one the arms, and the other the legs).
@@ -245,7 +270,7 @@ addToRootBone(bone1)
Tip: Use the AnimEventLister below to react at the end or start of an animation cycle.
@@ -328,7 +353,7 @@ The onAnimCycleDone() event is invoked when an animation cycle has ended. For no
You have access to the following objects:
Requirements
+
-
+
-
@@ -62,26 +87,26 @@ What is required in your java class?
The Controller
+The Animation Control
com.jme3.animation.AnimControl
object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controllers. The control object gives you access to the available animation sequences in the model.
+Create one com.jme3.animation.AnimControl
object in your JME3 application for each animated model that you want to control. You have to register each animated model to one of these Animation Controls. The control object gives you access to the available animation sequences in the model.
AnimControl playerControl; // you need one controller per model
+
AnimControl playerControl; // you need one Control per model
Node player = (Node) assetManager.loadModel("Models/Oto/Oto.mesh.xml"); // load a model
playerControl = player.getControl(AnimControl.class); // get control over this model
playerControl.addListener(this); // add listener
Channels
+Animation Channels
com.jme3.animation.AnimChannel
). Each channel can play one animation sequence at a time.
+An Animation Control has several Animation Channels (com.jme3.animation.AnimChannel
). Each channel can play one animation sequence at a time.
control.clearChannels();
+To reset a Control, call control.clearChannels();
clearListeners() Adds or removes listeners to receive animation related events.
-
+
@@ -148,7 +173,7 @@ removeAnim(boneAnim)AnimControl Property Usage
Adds or removes an animation from this Control. getAnimationLength("anim")Returns the length of the given named animation in seconds
+
@@ -162,7 +187,7 @@ removeAnim(boneAnim)AnimControl Property Usage
Adds or removes an animation from this Control. getAttachmentsNode("bone")Returns the attachment node of a bone. Attach models and effects to this node to make them follow this bone's motions.
Animation Channel Properties
@@ -193,7 +218,7 @@ The following properties are set per AnimChannel.
setTime(1.3f); Fast-forward or rewind to a certain moment in time of this animation.
getControl() The AnimControl that belongs to this AnimChannel.
Add a series of bones to be influenced by this ani
addFromRootBone(bone1) Add a series of bones to be influenced by this animation channel: Add all bones, starting from the given root bone, going towards the children bones.
-
+
Playing Animations
@@ -265,7 +290,7 @@ Animations are played by channel. Note: Whether the animation c
The float value specifies the time how long the animation should overlap with the previous one on this channel. If set to 0f, then no blending will occur and the new animation will be applied instantly.
-
+
-
-com.jme3.app.state.AppState
is a customizable jME3 interface that allows you to control the global game logic (game mechanics). To control the behaviour of a type of Spatial, see Custom Controls instead – both can be used together.
+
+The com.jme3.app.state.AppState
class is a customizable jME3 interface that allows you to control the global game logic – the overall game mechanics. (To control the behaviour of a Spatial, see Custom Controls instead. Controls and AppStates can be used together.)
-There will be situations during your game development where you think: +There are situations during your game development where you think:
-Yes you can! This is what AppStates are there for. A game state can be a subset of class fields (game data), GUI elements and their interactions, a subset of input handlers, a subset of nodes in the simpleInitApp() method, a subset of actions that you branch to in the simpleUpdate() loop, a set of AppStates and Controls – or combinations thereof. +You can! This is what AppStates are there for. An AppState class is subset of (or an extension to) your application. Every AppState class has access to all fields in your main application (AssetManager, ViewPort, StateManager, InputManager, RootNode, GuiNode, etc) and hooks into the main update loop. An AppState can contain:
+-Each AppState is such a grouped subset of such game states. Each AppState has hooks that let you define what happens to this set in the following situations: + +Each AppState lets you define what happens in the following situations:
update()
loop. -Tip: You can create AppStates that enable and disable sets of other AppStates, e.g. InGameState versus MainScreenState. +
@@ -60,7 +95,9 @@ Each AppState is such a grouped subset of such game states. Each AppState has ho To implement game logic:
stateManager.attach(myAppState);
), and activate and deactivate the ones you need.stateManager.attach(myAppState);
).-When you add several AppStates to one Application and activate them, their init methods and update loops are executed in the order in which the AppStates were added. +When you add several AppStates to one Application and activate them, their initialize() methods and update() loops are executed in the order in which the AppStates were added to the AppStateManager.
@@ -89,7 +126,7 @@ When you add several AppStates to one Application and activate them, their init JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include:
-The AppState interface allows you to initialize sets of objects, and hook a sets of continously executing code into the main loop. +The AppState interface lets you initialize sets of objects, and hook a set of continously executing code into the main loop.
AppState Method | Usage | ||
---|---|---|---|
stateAttached(asm) -stateDetached(asm) | The AppState knows when it is attached to, or detached from, the AppStateManager, and triggers these two methods. Here you implement what happens then. | +initialize(asm,app) | When this AppState is added to the game, the RenderThread initializes the AppState and then calls this method. You can modify the scene graph from here (e.g. attach nodes). To get access to the main app, call: super.initialize(stateManager, app); +this.app = (SimpleApplication) app;+ |
initialize(asm,app) | The RenderThread initialized the AppState and then calls this method. Here you implement initSimpleApp()-style initialization code. | +cleanup() | This methid is executed after you remove the AppState from the game. Here you implement clean-up code for when this state is detached. You can modify the scene graph from here (e.g. detach nodes). |
isInitialized() | Your implementations of this interface should return the correct respective boolean value. | +update(float tpf) | Here you implement the behaviour that you want to hook into the simpleUpdate() loop while this state is attached to the game. You can modify the scene graph from here. |
setActive(true) -setActive(false) | Temporarily enables or disables an AppState. | +isInitialized() | Your implementations of this interface should return the correct respective boolean value. (See AbstractAppState) |
isActive() | Test whether AppState is enabled or disabled. Your implementation should consider the boolean. | +setActive(true) +setActive(false) | Temporarily enables or disables an AppState. (See AbstractAppState) |
update(float tpf) | Here you implement the behaviour that you want to hook into the simpleUpdate() loop. | +isActive() | Test whether AppState is enabled or disabled. Your implementation should consider the boolean. (See AbstractAppState) |
cleanup() | Called when when the AppState is de-initialized. Here you implement what clean-up code for this state. | +stateAttached(asm) +stateDetached(asm) | The AppState knows when it is attached to, or detached from, the AppStateManager, and triggers these two methods. Don't modify the scene graph from here! (Typically not used.) |
render(RenderManager rm) | Renders the state, plus your optional customizations. | +render(RenderManager rm) | Renders the state, plus your optional customizations. (Typically not used.) |
postRender() | Called after all rendering commands are flushed, including your optional customizations. | +postRender() | Called after all rendering commands are flushed, including your optional customizations. (Typically not used.) |
-The AbstractAppState class already implements some common methods and makes creation of custom AppStates a bit easier: isInitialized(), setActive(), isActive(), cleanUp(). Just extend it and override the remaining AppState methods.
+The AbstractAppState class already implements some common methods (isInitialized(), setActive(), isActive()
) and makes creation of custom AppStates a bit easier. We recommend you extend AbstractAppState and override the remaining AppState methods: initialize(), setEnabled(), cleanUp()
.
+
Definition:
public class MyAppState extends AbstractAppState { - private Node x = new Node("x"); // some class field + private SimpleApplication app; - public Node getX(){ - return x; // implement custom methods for this field + private Node x = new Node("x"); // some custom class fields... + public Node getX(){ return x; } // some custom methods... + + @Override + public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + this.app = (SimpleApplication)app; // cast to a more specific class + + // init stuff that is independent of whether state is PAUSED or RUNNING + this.app.getRootNode().attachChild(getX()); // modify scene graph... + this.app.doSomething(); // call custom methods... + } + + @Override + public void cleanup() { + super.cleanup(); + // unregister all my listeners, detach all my nodes, etc... + this.app.getRootNode().detachChild(getX()); // modify scene graph... + this.app.doSomethingElse(); // call custom methods... } @Override - public void update(float tpf) { - x.doSomething(); // call some methods here + public void setEnabled(boolean enabled) { + // Pause and unpause + super.setEnabled(enabled); + if(enabled){ + // init stuff that is in use while this state is RUNNING + this.app.getRootNode().attachChild(getX()); // modify scene graph... + this.app.doSomethingElse(); // call custom methods... + } else { + // take away everything not needed while this state is PAUSED + ... + } } @Override - public void initialize(AppStateManager stateManager, Application app) { - super.initialize(stateManager, app); - this.app=(SimpleApplication)app; - app.doSomething(); // call some methods elsewhere + public void update(float tpf) { + if(isEnabled()){ + // do the following while game is RUNNING + this.app.getRootNode().getChild("blah").scale(tpf); // modify scene graph... + x.setUserData(...); // call some methods... + } else { + // do the following while game is PAUSED, e.g. play an idle animation. + ... + } } + }+
+
+You define what an AppState does when Paused or Unpaused, in the setEnabled()
and update()
methods. Call myState.setEnabled(false)
on all states that you want to pause. Call myState.setEnabled(true)
on all states that you want to unpause.
+
-The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates are updated and rendered. When an AppState is attached, AppStateManager calls its stateAttached() method. When an AppState is detached, AppStateManager calls its stateDetached() method. -There is one AppStateManager per application. You can attach several AppStates to one AppStateManager, but the same state can only be attached once. + +The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that activate AppStates can modify the scene graph, and that the update() loops of active AppStates is executed. There is one AppStateManager per application. You typically attach several AppStates to one AppStateManager, but the same state can only be attached once. +
AppStateManager Method | Usage | ||
---|---|---|---|
hasState(s) | Is AppState s attached? | +hasState(myState) | Is AppState object 'myState' attached? |
getState(Class<T> stateClass) | Returns the first state that is an instance of a subclass of the specified class. | +getState(MyAppState.class) | Returns the first attached state that is an instance of a subclass of MyAppState.class . |
-The AppStateManager's update(), render(), postRender(), and cleanUp() methods are internal, users never call them directly.
+The AppStateManager's render(), postRender(), cleanUp()
methods are internal, ignore them, users never call them directly.
-You can only change AppStates, or read and write to them, from certain places: In a Control's update() method, in an AppState's update() method, and in the SimpleApplication's simpleUpdate() loop (or the Application's update() loop).
-To get data from the AppState MyAppState
:
+
app.getState(MyAppState.class).getInfoAboutSomething();+
-To pass new data into the AppState MyAppState
:
-
+You can only access other AppStates (read from and write to them) from certain places: From a Control's update() method, from an AppState's update() method, and from the SimpleApplication's simpleUpdate() loop. Don't mess with the AppState from other places, because from other methods you have no control over the order of modifications; the game can go out of sync because you can't know when (during which half-finished step of another state change) your modification will be performed.
app.getState(MyAppState.class).setSomething(blah);
-
-To trigger a one-off method in the AppState MyAppState
:
+You can use custom accessors to get data from AppStates, to set data in AppStates, or to trigger methods in AppStates.
app.getState(MyAppState.class).doSomeMoreStuff();+
this.app.getStateManager().getState(MyAppState.class).doSomeCustomStuffInThisState();-
+
+To access class fields of the application the way you are used to, initialize them to local variables:
+private SimpleApplication app; +private Node rootNode; +private AssetManager assetManager; +private AppStateManager stateManager; +private InputManager inputManager; +private ViewPort viewPort; +private BulletAppState bullet; + +public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + this.app = (SimpleApplication) app; // can cast Application to something more specific + this.rootNode = this.app.getRootNode(); + this.assetManager = this.app.getAssetManager(); + this.stateManager = this.app.getStateManager(); + this.inputManager = this.app.getInputManager(); + this.viewPort = this.app.getViewPort(); + this.bullet = this.stateManager.getState(BulletAppState.class); +}
jMonkeyProjects/MyGame/assets/ # You store assets in subfolders here! <------ +jMonkeyProjects/MyGame/build/ # SDK generates built classes here (*) +jMonkeyProjects/MyGame/build.xml # You customize Ant build script here +jMonkeyProjects/MyGame/nbproject/ # SDK stores default build.xml and meta data (*) +jMonkeyProjects/MyGame/dist/ # SDK generates executable distribution here (*) +jMonkeyProjects/MyGame/src/ # You store Java sources here +jMonkeyProjects/MyGame/test/ # You store test classes here (optional) +(*) Managed by jMonkeyEngine SDK -- don't edit!+ +
+See also Best Practices. +
+ +
+
The assetManager
object is an com.jme3.asset.AssetManager instance that every com.jme3.app.Application can access. It maintains a root that also includes your project's classpath by default, so you can load any asset that's on the classpath, that is, the top level of your project directory.
-You can use the inherited assetManager
object directly, or use the accessor getAssetManager()
.
+You can use the inherited assetManager
object directly, or use the accessor app.getAssetManager()
.
-Here is an example how you load assets using the AssetManager. This lines loads a default Material from the Common directory:
+Here is an example how you load assets using the AssetManager. This lines loads a default Material from the built-in Common/
directory:
Material mat = (Material) assetManager.loadAsset( new AssetKey("Common/Materials/RedColor.j3m"));
-The Material is "somewhere" in the jME3 JAR, but the default Asset Manager is configured to handle a Common/…
path correctly, so you don't have to specify the whole path.
+This Material is "somewhere" in the jME3 JAR; the default Asset Manager is configured to handle a Common/…
path correctly, so you don't have to specify the whole path when referring to built-in assets (such as default Materials).
-Additionally, You can configure the Asset Manager and add any path to its root. This means, you can load assets from any project directory you specify. +Additionally, you can configure the Asset Manager and add any path to its root. This means, you can load assets from any project directory you specify. The next example shows how you load assets from your project's assets directory.
@@ -42,24 +65,34 @@ By default, jME3 searches for models in a directory named assets
. <
This is our recommended directory structure for storing assets:
-MyGame/assets/Interface/ -MyGame/assets/MatDefs/ -MyGame/assets/Materials/ -MyGame/assets/Models/ -MyGame/assets/Scenes/ -MyGame/assets/Shaders/ -MyGame/assets/Sounds/ -MyGame/assets/Textures/ -MyGame/build.xml # build script -MyGame/src/... # source code+
jMonkeyProjects/MyGame/src/... # Packages, .java source code. +jMonkeyProjects/MyGame/assets/... # The assets directory: +jMonkeyProjects/MyGame/assets/Interface/ # .font, .jpg, .png, .xml +jMonkeyProjects/MyGame/assets/MatDefs/ # .j3md +jMonkeyProjects/MyGame/assets/Materials/ # .j3m +jMonkeyProjects/MyGame/assets/Models/ # .j3o +jMonkeyProjects/MyGame/assets/Scenes/ # .j3o +jMonkeyProjects/MyGame/assets/Shaders/ # .j3f, .vert, .frag +jMonkeyProjects/MyGame/assets/Sounds/ # .ogg, .wav +jMonkeyProjects/MyGame/assets/Textures/ # .jpg, .png; also .mesh.xml+.material, .mtl+.obj, .blend (!)+ +
+These are just the most common examples. You can rename/delete/add directories and subdirectories inside the assets
directory in any way you like. Note however that there is no automatic refactoring for asset paths in the SDK, so if you modify them late in the development process, you have to refactor all paths manually.
+
-These are just the most common examples. You can name the directories inside the assets
directory what ever you like.
+Examples: You can rename assets/Sounds
to assets/Audio
, you can delete assets/MatDefs
if you don't use it, you can create assets/AIscripts
, etc. You can rename/move the assets/Textures
directory or its subdirectories, but then you have to re-export all models, and re-convert them all to .j3o, so plan ahead!
+
+
assets/Textures/
before you work with them in a mesh editor! Export and save 3D model files (.mesh.xml+.material, .mtl+.obj, .blend) into the assets/Textures/
(!) before you convert the model to binary format (.j3o)! This ensures that texture paths correctly point to the assets/Textures
directory. assets/Models/
or assets/Scenes/
directories. This way, you can reuse textures, your binaries consistently link the correct textures, and the assets/Models
and assets/Scenes
directories don't become cluttered.
+@@ -71,7 +104,6 @@ Creating a material instance with the definition "Unshaded.j3md": assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
- Applying a texture to the material:
@@ -111,7 +143,8 @@ jME3 also offers a ClasspathLocator, ZipLocator, FileLocator, HttpZipLocator, an-Note: The custom build script does not automatically include ZIP files in the executable build. +
-Even if the game runs fine when started from the jMoneykPlatform, an error message similar to the following can occur in the console when you run the stand-alone executables (.JAR, .JNLP, etc). +Problem: +
+ ++My game runs fine when I run it right from the jMonkeyEngine SDK. But when I run the stand-alone executables (.jar, .jnlp .exe, .app), a DesktopAssetManager error message occurs in the console, and it quits?
com.jme3.asset.DesktopAssetManager loadAsset WARNING: Cannot locate resource: Scenes/town/main.scene @@ -163,7 +200,7 @@ java.lang.NullPointerException
-If you use the default build script created by the jMonkeyEngine SDK then the original OgreXML files are not included in the executable. A stand-alone executable works with .j3o files only. The default build script makes sure to include .j3o files in the executable. +If you use the default build script, original models and scenes, and ZIP files, are excluded from the distribution automatically. A stand-alone executable includes converted .j3o models and scenes only. The default build script makes sure to include existing .j3o files in the distribution, but you need to convert the models manually.
@@ -171,41 +208,73 @@ If you use the default build script created by the jMonkeyEngine
-Before building the executable, you must use the jMonkeyEngine SDK's context menu action to convert OgreXML models to .j3o format.
+Before building the executable, you must use the jMonkeyEngine SDK's context menu action to convert 3D models to .j3o binary format.
-If you load the scene from a non.j3o ZIP file, expand the default_build_script to copy the ZIP files.
+
assets
directory in the Projects window. assets
directory in the Projects window. assets/Models/
or assets/Scenes/
directories.load()
code to access the .j3o file.
-If you are using another IDE than jMonkeyEngine SDK for coding, you should create a so-called codeless project in the jMonkeyEngine SDK to maintain assets. This method will not meddle with your sources or custom build scripts. It simply makes it easier for you to browse game assets, and preview, arrange, and especially convert models to binary. +Problem: +
+ +
+I use another IDE than jMonkeyEngine SDK for coding (Eclipse, IntelliJ, text editor). Where is my asset
folder and .j3o converter?
+
+Solution: +
+ ++You can code in any IDE, but you must create a so-called codeless project in the jMonkeyEngine SDK to maintain assets. A code-less jMonkeyEngine project does not meddle with your sources or custom build scripts. You merely use it to convert models to .j3o binaries. +
-assets
. + +
AudioNode Method | Usage | All 3D effects switched off. This sound is global | setMaxDistance(100f) | Maximum distance the sound can be heard, in world units. Default is 20. |
---|
AudioNode Method | Usage | Activates 3D audio: The sound appears to come f | setReverbEnabled(true) | A 3D echo effect that only makes sense to use with positional AudioNodes. The reverb effect is influenced by the environment that the audio renderer is in. See "Setting Environment Properties" below. |
---|
AudioNode Method | Usage | Activates 3D audio: This sound can only be heard from setOuterAngle() | Set the angle in degrees for the directional audio. The angle is relative to the direction. Note: By default, both angles are 360° and the sound can be heard from all directions! |
---|
c
Closet 1.00f 1.0f 1.0f 1.00f 0.15f 1.0f 0.600f 0.0025f 0.500f 0.0006f
Activate the preset with setEnvironment(). E.g. in a dungeon environment: diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html index 927b1897b..b29a3c2be 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/bloom_and_glow.html @@ -86,8 +86,8 @@ Here you can see the diffuse map of the tank, and the associated glow map that o
-Glow maps works with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions. -The tank material looks like that : +Glow maps work with Lighting.j3md, Particles.j3md and SolidColor.j3md material definitions. +The tank material looks like this :
Material My Material : Common/MatDefs/Light/Lighting.j3md { @@ -279,6 +279,11 @@ If you are using a glow color, set it to blackmaterial.setColor("GlowColor",ColorRGBA.Black);++ documentation, + effect, + light +\ No newline at end of file diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html index 86b01456c..0f158d7d1 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/camera.html @@ -94,7 +94,7 @@ The camera object is created with the following defaults:-The flyby camera is an extension of the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and for strafing to the sides. Move the mouse to rotate the camera, scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera. +The flyby camera is an AppState that extends the default camera in com.jme3.app.SimpleApplication. It is preconfigured to respond to the WASD keys for walking forwards and backwards, and strafing to the sides; move the mouse to rotate the camera ("Mouse Look"), scroll the mouse wheel for zooming in or out. The QZ keys raise or lower the camera vertically.
- +@@ -111,10 +111,10 @@ The flyby camera is an extension of the default camera in com.jme3.app.SimpleApp
flyCam.setRotationSpeed(10); Control the rotation speed - flyCam.setDragToRotate(true) Must keep mouse button pressed to rotate camera. Used e.g. for Applets. if false, all mouse movement will be captured and interpreted as rotations. +flyCam.setDragToRotate(true) Forces the player to keep mouse button pressed to rotate camera, typically used for Applets. If false (default), all mouse movement will be captured and interpreted as rotations. Chase Camera
@@ -164,7 +164,7 @@ ChaseCamera chaseCam = new ChaseCamera(cam, target, inputManager);
-
So you've made your cool new JMonkeyEngine3 game and you want to create a demo video to show off your hard work. Or maybe you want to make a cutscene for your game using the physics and characters in the @@ -64,6 +56,14 @@ That's all!
+
If you want to record audio as well, record at different framerates, or record from multiple viewpoints at once, then there's a full solution for doing this already made for you here: diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html index 7c61809a5..b5cca9015 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_controls.html @@ -3,7 +3,11 @@
-A com.jme3.scene.control.Control
is a customizable jME3 interface that allows you to cleanly steer the behaviour of game entities: Traps, alarms, doors, animal NPCs, self-steering vehicles, artificially intelligent behaviour in NPCs, anything that moves. Several instances of Controls together implement the behaviours of a type of Spatial. To control global game behaviour see Application States – you can also use both together.
+A com.jme3.scene.control.Control
is a customizable jME3 interface that allows you to cleanly steer the behaviour of game entities (Spatials), such as artificially intelligent behaviour in NPCs, traps, automatic alarms and doors, animals and pets, self-steering vehicles or platforms – anything that moves and interacts. Several instances of customs Controls together implement the behaviours of a type of Spatial.
+
+To control global game behaviour see Application States – you often use AppStates and Control together.
com.jme3.scene.control.Control
is a customizable jME3 interface t
-To control the behaviour of types of entities: +To control the behaviour of spatials:
spatial
gives you access to the spatial that the control is attached to.spatial
gives you access to the spatial and subspatials that the control is attached to.spatial
's transformation (move, scale, rotate), play animations, check for enemies around it and react, etc. spatial
's transformation (move, scale, rotate), play animations, check its environement, define how it acts and reacts. spatial.addControl(myControl);+
spatial.addControl(myControl);
-To implement game logic for a type of spatial, you will either extend AbstractControl, or implement the Control interface, as explained in this article. +To implement game logic for a type of spatial, you will either extend AbstractControl (most common case), or implement the Control interface, as explained in this article.
-For example, you could write a CharacterAnimControl that animates a character accordingly while it is being moved by a CharacterControl. Or you can write an AIControl that remote-controls NPC behaviour in fight situatons. Or you could write a DestructionControl that automatically replaces a structure with an appropriate piece of debris after collision with a projectile… The possibilities are endless.
+
+Use Controls to implement the behaviour of types of game entities.
+
update()
loop that hooks into simpleUpdate()
. Use Controls to move blocks of code out of the simpleUpdate()
loop.+ +Examples: You can write +
+
+
+The possibilities are endless.
+
+ +Other examples include the built-in RigidBodyControl in JME's physics integration, the built-in TerrainLODControl that updates the terrain's level of detail depending on the viewer's perspective, etc. +
+ +Existing examples in the code base include:
+ +
+The AbstractControl can be found under com.jme3.scene.control.AbstractControl
. This is a default abstract class that implements the Control interface.
+
isEnabled()
.spatial
. controlUpdate()
method to implement the Spatial's behaviour. setEnabled(boolean)
method. This activates or deactivates this Control's behaviour in this spatial temporarily. While the AbstractControl is toggled to be disabled, the controlUpdate()
loop is no longer executed.
+
+Usage: Your custom subclass implements the three methods controlUpdate()
, controlRender()
, setSpatial()
, and cloneForSpatial()
as shown here:
+
public class MyControl extends AbstractControl implements Savable, Cloneable { + privat int index; // can have custom fields -- example + + public MyControl(){} // empty serialization constructor + + /** Optional custom constructor with arguments that can init custom fields. + * Note: you cannot modify the spatial here yet! */ + public MyControl(int i){ + // index=i; // example + } + + /** This is your init method. Optionally, you can modify + * the spatial from here (transform it, initialize userdata, etc). */ + @Override + public void setSpatial(Spatial spatial) { + super.setSpatial(spatial); + // spatial.setUserData("index", i); // example + } + + + /** Implement your spatial's behaviour here. + * From here you can modify the scene graph and the spatial + * (transform them, get and set userdata, etc). + * This loop controls the spatial while the Control is enabled. */ + @Override + protected void controlUpdate(float tpf){ + if(spatial != null) { + // spatial.rotate(tpf,tpf,tpf); // example behaviour + } + } + + @Override + public Control cloneForSpatial(Spatial spatial){ + final MyControl control = new MyControl(); + /* Optional: use setters to copy userdata into the cloned control */ + // control.setIndex(i); // example + control.setSpatial(spatial); + return control; + } + + @Override + protected void controlRender(RenderManager rm, ViewPort vp){ + /* Optional: rendering manipulation (for advanced users) */ + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + // im.getCapsule(this).read(...); + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + // ex.getCapsule(this).write(...); + } + +}+ +
+See also: +
+setUserData()
, see Spatial.
-The interface can be found under com.jme3.scene.control.Control
. It has the following method signatures:
+
+
+The Control interface can be found under com.jme3.scene.control.Control
. It has the following method signatures:
cloneForSpatial(Spatial)
: Clones the Control and attaches it to a clone of the given Spatial. The AssetManager uses this method if the same spatial is loaded twice. You can specify which fields you want your object to reuse (e.g. collisionshapes) in this case. cloneForSpatial(Spatial)
: Clones the Control and attaches it to a clone of the given Spatial. setEnabled(boolean)
: Enable or disable the control. If disabled, update() does nothing. Goes with accessor isEnabled();
.setEnabled(boolean)
: Toggles a boolean that enables or disables the Control. Goes with accessor isEnabled();
. You test for it in the update(float tpf)
loop before you execute anything.setSpatial(Spatial s)
, update(float tpf);
, render(RenderManager rm, ViewPort vp)
.-If you want to create a Control that also extends an existing class, then create a custom extension of the Control Interface. Usage example: + +Usage example: 1. Create a custom control interface
-public interface MyControl extends Control { - public void setSomething(int x); // add your custom methods +public interface MyControlInterface extends Control { + public void setSomething(int x); // optionally, add custom methods }-2. Create custom classes implementing your control interface +2. Create custom Controls implementing your Control interface.
-public class ControlledThing extends MyThing implements MyControl { +public class MyControl extends MyCustomClass implements MyControlInterface { protected Spatial spatial; protected boolean enabled = true; - public ControlledThing() { } // empty serialization constructor + public MyControl() { } // empty serialization constructor - public ControlledThing(int x) { // custom constructor + public MyControl(int x) { // custom constructor super(x); } @Override public void update(float tpf) { if (enabled && spatial != null) { - // ... // Write custom code to control the spatial here! } } @@ -116,16 +277,17 @@ If you want to create a Control that also extends an existing class, then create @Override public Control cloneForSpatial(Spatial spatial) { - ControlledThing control = new ControlledThing(y); + MyControl control = new MyControl(); // set custom properties - spatial.setControl(control); + control.setSpatial(spatial); + control.setEnabled(isEnabled()); + // set some more properties here... return control; } @Override public void setEnabled(boolean enabled) { this.enabled = enabled; - // ... } @Override @@ -158,84 +320,11 @@ If you want to create a Control that also extends an existing class, then create
-
-This class can be found under com.jme3.scene.control.AbstractControl
.
-
enabled
, and a Spatial spatial
.
-
-Usage: Your custom subclass implements the three methods controlUpdate()
, controlRender()
, setSpatial()
, and cloneForSpatial()
as shown here:
-
public class MyControl extends AbstractControl implements Savable, Cloneable { - - private Thing thing; // some custom field of yours - - public MyControl(){} // empty serialization constructor - - public MyControl(thing) { // some custom constructor - this.thing = thing; - // Note: you can not access spatial here - } - - @Override - public void setSpatial(Spatial spatial) { - super.setSpatial(spatial); - // optional init method - // you can get and set user data in the spatial here - } - - @Override - protected void controlUpdate(float tpf){ - if(spatial != null && thing != null) { - // Implement your custom control here ... - // Change scene graph, access and modify userdata in the spatial, etc - } - } - - @Override - protected void controlRender(RenderManager rm, ViewPort vp){ - // optional rendering manipulation (for advanced users) - } - - @Override - public Control cloneForSpatial(Spatial spatial){ - final MyControl control = new MyControl(...); - control.setSpatial(spatial); - return control; - } - - @Override - public void read(JmeImporter im) throws IOException { - super.read(im); - // im.getCapsule(this).read(...); - } - - @Override - public void write(JmeExporter ex) throws IOException { - super.write(ex); - // ex.getCapsule(this).write(...); - } - -}- -
+ Tip: Use the getControl() accessor to get Control objects from Spatials. No need to pass around lots of object references. Here an example from the code: diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html index 92db2cafc..a6fe7225b 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/custom_meshes.html @@ -115,14 +115,14 @@ The Mesh data is stored in a buffer.
com.jme3.scene.VertexBuffer.Type
.mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices)); mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord)); -mesh.setBuffer(Type.Index, 1, BufferUtils.createIntBuffer(indexes)); +mesh.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(indexes)); mesh.updateBound();
@@ -172,7 +172,8 @@ Vertex coloring is a simple way of coloring meshes. Instead of just assigning on
Geometry geo = new Geometry ("ColoredMesh", mesh); -Material matVC = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");+Material matVC = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); +matVC.setBoolean("VertexColor", true);
diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html index 22bf96f35..eb92f43c9 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/effects_overview.html @@ -1,5 +1,5 @@ -
inputManager.deleteMapping( SimpleApplication.INPUT_MAPPING_MEMORY );+
Default Mapping | Key | Description | +
---|---|---|
INPUT_MAPPING_HIDE_STATS | F5 | Hides the statistics in the bottom left. | +
INPUT_MAPPING_CAMERA_POS | KEY_C | Prints debug output about the camera. | +
INPUT_MAPPING_MEMORY | KEY_M | Prints debug output for memtory usage. | +
INPUT_MAPPING_EXIT | KEY_ESCAPE | Closes the application by calling stop(); . Typically you do not remove this, unless you replace it by another way of quitting gracefully. |
+
@@ -159,7 +182,7 @@ inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D
diff --git a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html index 9ec9bb6ce..957c701f9 100644 --- a/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html +++ b/sdk/jme3-core/javahelp/com/jme3/gde/core/docs/jme3/advanced/j3m_material_files.html @@ -7,6 +7,10 @@ In the Material Definitions article you learned how to configure Materials programmatically in Java code. If you have certain commonly used Materials that never change, you can clean up the amount of Java code that clutters your init method, by moving material settings into .j3m files. Then later in your code, you only need to call one setter instead of several to apply the material.
++If you want to colorize simple shapes (one texture all around), then .j3m are the most easily customizable solution. J3m files can contain texture mapped materials, but as usual you have to create the textures in an external editor, especially if you use UV-mapped textures. +
+-Tip: In the jMonkeyEngine SDK, use File>New File>Material>Empty Material File to create .j3m files. +