/** Given the Avatar character, create and set it's collision controller. */ private void setCollisionController(WlAvatarCharacter avatar) { // Create a spatial that represents the bounds of the avatar to use // for collision. These are hardcoded values for now. Vector3f origin = new Vector3f(0f, 0.57f, 0.0f); float radius = 0.25f; if (selectedForInput) { Spatial collisionGraph = new Sphere("AvatarCollision", origin, 10, 10, radius); collisionGraph.setModelBound(new BoundingBox()); collisionGraph.updateModelBound(); // Fetch the JME Collision system using the server manager of the Cell // to which this renderer is attached. ServerSessionManager manager = cell.getCellCache().getSession().getSessionManager(); CollisionSystem collisionSystem = ClientContextJME.getCollisionSystem(manager, "Default"); // Create a new collision controller, and set on the avatar CollisionController controller = new CollisionController(collisionGraph, (JMECollisionSystem) collisionSystem); collisionChangeRequestListener.setCollisionController(controller); AvatarController ac = (AvatarController) avatar.getContext().getController(); ac.setCollisionController(controller); if (collisionListener == null) { collisionListener = new WLCollisionListener(); } ac.addCollisionListener(collisionListener); } else { AvatarController ac = (AvatarController) avatar.getContext().getController(); ac.setCollisionController(null); ac.removeCollisionListener(collisionListener); } }
public void trigger(int trigger, boolean pressed, String animationName) { if (!selectedForInput && avatarCharacter != null) { // Sync to avoid concurrent updates of currentTrigger and currentPressed synchronized (this) { if (currentTrigger == trigger && currentPressed == pressed) { return; } try { if (pressed) { if (animationName != null) { ((WlAvatarContext) avatarCharacter.getContext()).setMiscAnimation(animationName); } avatarCharacter.getContext().triggerPressed(trigger); } else { avatarCharacter.getContext().triggerReleased(trigger); } } catch (Exception e) { // We can get this if a user is viewing a female avatar but // has not yet set female as the default. } currentTrigger = trigger; currentPressed = pressed; } } }
protected void updatePickGeometry() { // clean up any existing pick geometry if (pickGeometry != null) { pickGeometry.detach(); pickGeometry = null; } // make sure we are pickable and ready to add geometry if (!isPickable() || avatarCharacter.getJScene() == null) { return; } if (avatarCharacter.getSkeleton() != null) { // use pick geometry for an IMI avatar boolean isMale = avatarCharacter.getCharacterParams().isMale(); PickBox[] pickBoxes = getPickBoxes(isMale); pickGeometry = new ImiPickGeometry(cell.getName(), cell, AvatarImiJME.this, pickBoxes); } else if (avatarCharacter.getSimpleStaticGeometry() != null) { pickGeometry = new BasicPickGeometry( cell.getName(), cell, this, avatarCharacter.getSimpleStaticGeometry()); } }
public void selectForInput(boolean selected) { if (selectedForInput == selected) return; if (avatarCharacter == null) { logger.warning("selectForInput called with null avatarCharacter"); Thread.dumpStack(); return; } logger.info("selectedForInput " + selected); selectedForInput = selected; if (avatarCharacter != null) { WorldManager wm = ClientContextJME.getWorldManager(); ((WlAvatarContext) avatarCharacter.getContext()).getBehaviorManager().setEnable(false); if (controlScheme == null && selectedForInput) { controlScheme = new DefaultCharacterControls(ClientContextJME.getWorldManager()); ((AvatarControls) wm.getUserData(AvatarControls.class)).setDefault(controlScheme); } setCollisionController(avatarCharacter); if (selectedForInput) { // Listen for avatar movement and update the cell avatarCharacter .getContext() .getController() .addCharacterMotionListener(characterMotionListener); // Listen for game context changes avatarCharacter.getContext().addGameContextListener(gameContextListener); avatarCharacter.selectForInput(); controlScheme.addCharacterToTeam(avatarCharacter); controlScheme.setCharacter(avatarCharacter); // Chain the camera processor to the avatar motion processor for // smooth animation. For animated avatars we use CharacterAnimationProcessor for the simple // avatar CharacterProcessor ProcessorCollectionComponent pcc = avatarCharacter.getComponent(ProcessorCollectionComponent.class); ProcessorComponent characterProcessor = null; ProcessorComponent characterAnimationProcessor = null; for (ProcessorComponent pc : pcc.getProcessors()) { if (pc instanceof CharacterProcessor) characterProcessor = pc; else if (pc instanceof CharacterAnimationProcessor) { characterAnimationProcessor = pc; break; } } cameraChainedProcessor = null; if (characterAnimationProcessor != null) { cameraChainedProcessor = characterAnimationProcessor; } else if (characterProcessor != null) cameraChainedProcessor = characterProcessor; if (cameraChainedProcessor != null) { cameraChainedProcessor.addToChain(ViewManager.getViewManager().getCameraProcessor()); cameraChainedProcessor.setRunInRenderer(true); } // Disable culling for local avatar, fix for issue 799 avatarCharacter.getJScene().setCullHint(CullHint.Never); } else { avatarCharacter .getContext() .getController() .removeCharacterMotionListener(characterMotionListener); avatarCharacter.getContext().removeGameContextListener(gameContextListener); if (controlScheme != null) { controlScheme.clearCharacterTeam(); } if (cameraChainedProcessor != null) { cameraChainedProcessor.removeFromChain(ViewManager.getViewManager().getCameraProcessor()); cameraChainedProcessor = null; } // Reenable culling for local avatar, fix for issue 799 avatarCharacter.getJScene().setCullHint(CullHint.Dynamic); } } else { logger.severe("The avatar was null during enableInputListeners()."); } }
/** * Load and return the avatar. To make this the current avatar changeAvatar() must be called * * @param avatarConfigURL * @return */ private WlAvatarCharacter loadAvatarInternal(AvatarConfigInfo avatarConfigInfo) throws MalformedURLException, IOException { WlAvatarCharacter ret = null; PMatrix origin = new PMatrix(); CellTransform transform = cell.getLocalTransform(); origin.setTranslation(transform.getTranslation(null)); origin.setRotation(transform.getRotation(null)); // Create the character String avatarDetail = System.getProperty("avatar.detail", "high"); // check if we support high-quality avatars if (!supportsHighQualityAvatars()) { logger.warning("Forcing low detail."); avatarDetail = "low"; } // Check to see if there is no avatar configuration info and/or if we // have the avatar details set to "low". If so, then use the default AvatarLoaderRegistry registry = AvatarLoaderRegistry.getAvatarLoaderRegistry(); if (avatarConfigInfo == null || avatarDetail.equalsIgnoreCase("low")) { // Find the "default" factory to generate an avatar. Ask it to // loader the avatar. If it does not exist (it should), simply // log an error andr return. AvatarLoaderFactorySPI factory = registry.getDefaultAvatarLoaderFactory(); if (factory == null) { logger.warning("No default avatar factory is registered."); return null; } // We need to rewrite the AvatarConfigInfo object here a bit, // otherwise, the loader may still loader the wrong avatar. If // we set the URL in the AvatarConfigInfo to null, that should do // the trick. (Note that since we manually obtained the // AvatarLoaderFactorySPI, we don't need to update the factory // class name in the AvatarConfigInfo object, but we do anyway). String defaultClassName = factory.getClass().getName(); AvatarConfigInfo defaultInfo = new AvatarConfigInfo(null, defaultClassName); // Go ahead and load the default avatar ret = factory.getAvatarLoader().getAvatarCharacter(cell, username, defaultInfo); } else { // If the avatar has a non-null configuration information, then // ask the loader factory to generate a new loader for this avatar String className = avatarConfigInfo.getLoaderFactoryClassName(); if (className == null) { logger.warning( "No class name given for avatar configuration" + " with url " + avatarConfigInfo.getAvatarConfigURL()); return null; } // Find the avatar factory, if it does not exist, return an error AvatarLoaderFactorySPI factory = registry.getAvatarLoaderFactory(className); if (factory == null) { logger.warning( "No avatar loader factory for the class name " + className + " with url " + avatarConfigInfo.getAvatarConfigURL()); return null; } // Ask the avatar loader to create and return an avatar character ret = factory.getAvatarLoader().getAvatarCharacter(cell, username, avatarConfigInfo); } ret.getModelInst().getTransform().getLocalMatrix(true).set(origin); // XXX NPC HACK XXX // TODO - remove hardcoded npc support // if (username.equals("npc") && avatarConfigURL != null) { // String u = avatarConfigURL.getFile(); // username = u.substring(u.lastIndexOf('/') + 1, u.lastIndexOf('.')); // } // Sets the Z-buffer state on the external kids root Node external = ret.getJScene().getExternalKidsRoot(); setZBufferState(external); // JSCENE HAS NOT CHILDREN, so this does nothing // ret.getJScene().updateGeometricState(0, true); // GraphicsUtils.printGraphBounds(ret.getJScene()); // JScene jscene = avatar.getJScene(); // jscene.renderToggle(); // both renderers // jscene.renderToggle(); // jme renderer only // jscene.setRenderPRendererMesh(true); // Force pRenderer to be instantiated // jscene.toggleRenderPRendererMesh(); // turn off mesh // jscene.toggleRenderBoundingVolume(); // turn off bounds return ret; }
/** * Change the current avatar to the given avatar. * * <p>NOTE: This method must be called in the MT Game Render Thread. As such, we assume only one * of these methods is called at a time. * * @param newAvatar The new avatar to change to. */ private void changeAvatarInternal(WlAvatarCharacter newAvatar) { int flg = 0; if (newAvatar == null) return; // Turn on an indication that the avatar is being loaded LoadingInfo.startedLoading(cell.getCellID(), newAvatar.getName()); // Fetch the name tag node. There should be only one of these in the // system. Node nameTagNode = getNameTagNode(); // If there is an existing avatar character, then remove it, but store // away its position. Remove the name tag, turn off input and destroy // the avatar character. PMatrix currentLocation = null; if (avatarCharacter != null) { currentLocation = avatarCharacter.getModelInst().getTransform().getWorldMatrix(true); rootEntity.removeEntity(avatarCharacter); avatarCharacter.getJScene().getExternalKidsRoot().detachChild(nameTagNode); selectForInput(false); avatarCharacter.destroy(); flg = 1; } // Set the new avatar character. If there is none (when would that happen?) // then just return. avatarCharacter = newAvatar; if (newAvatar == null) { return; } // Add all of the default components to the renderer, but remove the // collision component, since we use our own collision graph RenderComponent rc = (RenderComponent) avatarCharacter.getComponent(RenderComponent.class); addDefaultComponents(avatarCharacter, rc.getSceneRoot()); avatarCharacter.removeComponent(CollisionComponent.class); // Set the initial location of the avatar if there is one if (currentLocation != null && avatarCharacter.getModelInst() != null) { logger.fine(cell.getCellID() + " Using current location: " + currentLocation); avatarCharacter.getModelInst().setTransform(new PTransform(currentLocation)); } else if (delayedMove != null && avatarCharacter.getModelInst() != null) { // there was no previous avatar, but there was a move that // happened while the avatar was null. Apply the move now logger.fine(cell.getCellID() + " using delayed move: " + delayedMove.toString()); PTransform trans = new PTransform( delayedMove.getRotation(null), delayedMove.getTranslation(null), new Vector3f(1, 1, 1)); avatarCharacter.getModelInst().setTransform(trans); } // Attach the name tag to the new avatar and add the avatar entity to // the cell renderer root entity and turn on input. Node externalRoot = avatarCharacter.getJScene().getExternalKidsRoot(); if (nameTagNode != null) { externalRoot.attachChild(nameTagNode); externalRoot.setModelBound(new BoundingSphere()); externalRoot.updateModelBound(); externalRoot.updateGeometricState(0, true); } rootEntity.addEntity(avatarCharacter); // Turn on input handle for the renderer, if we wish. Check for AvatarCell // to allow NPC's to work if (cell instanceof AvatarCell) { selectForInput(((AvatarCell) cell).isSelectedForInput()); } // Notify listeners that the avatar has changed. for (WeakReference<AvatarChangedListener> listenerRef : avatarChangedListeners) { AvatarChangedListener listener = listenerRef.get(); if (listener != null) { listener.avatarChanged(avatarCharacter); } else { avatarChangedListeners.remove(listenerRef); } } // update the bounds if necessary if (avatarCharacter.getJScene() != null) { avatarCharacter.getPScene().submitTransformsAndGeometry(true); avatarCharacter.getJScene().setModelBound(new BoundingSphere()); avatarCharacter.getJScene().updateModelBound(); avatarCharacter.getJScene().updateWorldBound(); } // Update pick geometry updatePickGeometry(); // Turn off the indication that we have finished loading LoadingInfo.finishedLoading(cell.getCellID(), newAvatar.getName()); // --added for sitting problem when user logs in--// // check If there is an existing avatar character if (flg == 0) { AvatarCell acell = (AvatarCell) cell; MovableAvatarComponent mac = (MovableAvatarComponent) acell.getComponent(MovableComponent.class); // check if avatar has trigger value of sitting if (mac.getServerTrigger() == 15) { avatarCharacter.getContext().triggerPressed(mac.getServerTrigger()); } } // --added for sitting problem when user logs in--// }
public void triggerCollision(float height, boolean collision) { if (!selectedForInput && avatarCharacter != null) { ((WlAvatarController) avatarCharacter.getController()).setHeight(height); ((WlAvatarController) avatarCharacter.getController()).setColliding(collision); } }