void SoundScriptManager::modulate(int actor_id, int mod, float value, int linkType, int linkItemID) { if (disabled) return; if (mod >= SS_MAX_MOD) return; for (int i = 0; i < free_gains[mod]; i++) { SoundScriptInstance* inst = gains[mod + i * SS_MAX_MOD]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { // this one requires modulation float gain = value * value * inst->templ->gain_square + value * inst->templ->gain_multiplier + inst->templ->gain_offset; gain = std::max(0.0f, gain); gain = std::min(gain, 1.0f); inst->setGain(gain); } } for (int i = 0; i < free_pitches[mod]; i++) { SoundScriptInstance* inst = pitches[mod + i * SS_MAX_MOD]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { // this one requires modulation float pitch = value * value * inst->templ->pitch_square + value * inst->templ->pitch_multiplier + inst->templ->pitch_offset; pitch = std::max(0.0f, pitch); inst->setPitch(pitch); } } }
SoundScriptInstance* SoundScriptManager::createInstance(Ogre::String templatename, int actor_id, Ogre::SceneNode* toAttach, int soundLinkType, int soundLinkItemId) { //first, search template SoundScriptTemplate* templ = NULL; if (templates.find(templatename) == templates.end()) { return NULL; // found no template with this name } templ = templates[templatename]; if (templ->trigger_source == SS_TRIG_NONE) { return NULL; // invalid template! } if (free_trigs[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP || (free_gains[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->gain_source != SS_MOD_NONE) || (free_pitches[templ->trigger_source] >= MAX_INSTANCES_PER_GROUP && templ->pitch_source != SS_MOD_NONE)) { LOG("SoundScriptManager: Reached MAX_INSTANCES_PER_GROUP limit (" + TOSTRING(MAX_INSTANCES_PER_GROUP) + ")"); return NULL; // reached limit! } SoundScriptInstance* inst = new SoundScriptInstance(actor_id, templ, sound_manager, templ->file_name + "-" + TOSTRING(actor_id) + "-" + TOSTRING(instance_counter), soundLinkType, soundLinkItemId); instance_counter++; // register to lookup tables trigs[templ->trigger_source + free_trigs[templ->trigger_source] * SS_MAX_TRIG] = inst; free_trigs[templ->trigger_source]++; if (templ->gain_source != SS_MOD_NONE) { gains[templ->gain_source + free_gains[templ->gain_source] * SS_MAX_MOD] = inst; free_gains[templ->gain_source]++; } if (templ->pitch_source != SS_MOD_NONE) { pitches[templ->pitch_source + free_pitches[templ->pitch_source] * SS_MAX_MOD] = inst; free_pitches[templ->pitch_source]++; } // SoundTrigger: SS_TRIG_ALWAYSON if (templ->trigger_source == SS_TRIG_ALWAYSON) { inst->start(); } return inst; }
void SoundScriptManager::trigOnce(int truck, int trig, int linkType, int linkItemID) { if (disabled) return; for (int i=0; i < free_trigs[trig]; i++) { // cycle through all instance groups SoundScriptInstance* inst = trigs[trig+i*SS_MAX_TRIG]; if (inst && inst->truck == truck && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { inst->runOnce(); } } }
void SoundScriptManager::trigKill(int truck, int trig, int linkType, int linkItemID) { if (disabled) return; if (!getTrigState(truck, trig, linkType, linkItemID)) return; state_map[linkType][linkItemID][truck][trig] = false; for (int i = 0; i < free_trigs[trig]; i++) { SoundScriptInstance* inst = trigs[trig + i*SS_MAX_TRIG]; if (inst && inst->truck == truck && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { inst->kill(); } } }
void SoundScriptManager::trigStop(int actor_id, int trig, int linkType, int linkItemID) { if (disabled) return; if (!getTrigState(actor_id, trig, linkType, linkItemID)) return; state_map[linkType][linkItemID][actor_id][trig] = false; for (int i = 0; i < free_trigs[trig]; i++) { SoundScriptInstance* inst = trigs[trig + i * SS_MAX_TRIG]; if (inst && inst->actor_id == actor_id && inst->sound_link_type == linkType && inst->sound_link_item_id == linkItemID) { inst->stop(); } } }
void TerrainObjectManager::loadObject(const Ogre::String &name, const Ogre::Vector3 &pos, const Ogre::Vector3 &rot, Ogre::SceneNode *bakeNode, const Ogre::String &instancename, const Ogre::String &type, bool enable_collisions /* = true */, int scripthandler /* = -1 */, bool uniquifyMaterial /* = false */) { ScopeLog log("object_"+name); if (type == "grid") { // some fast grid object hacks :) for (int x=0; x < 500; x += 50) { for (int z=0; z < 500; z += 50) { const String notype = ""; loadObject(name, pos + Vector3(x, 0.0f, z), rot, bakeNode, name, notype, enable_collisions, scripthandler, uniquifyMaterial); } } return; } // nice idea, but too many random hits //if (abs(rot.x+1) < 0.001) rot.x = Math::RangeRandom(0, 360); //if (abs(rot.y+1) < 0.001) rot.y = Math::RangeRandom(0, 360); //if (abs(rot.z+1) < 0.001) rot.z = Math::RangeRandom(0, 360); if (name.empty()) return; //FILE *fd; //char oname[1024] = {}; char mesh[1024] = {}; char line[1024] = {}; char collmesh[1024] = {}; Vector3 l(Vector3::ZERO); Vector3 h(Vector3::ZERO); Vector3 dr(Vector3::ZERO); Vector3 fc(Vector3::ZERO); Vector3 sc(Vector3::ZERO); Vector3 sr(Vector3::ZERO); bool forcecam=false; bool ismovable=false; int event_filter = EVENT_ALL; Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z); // try to load with UID first! String odefgroup = ""; String odefname = name + ".odef"; bool odefFound = false; bool exists = ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(odefname); if (exists) { odefgroup = ResourceGroupManager::getSingleton().findGroupContainingResource(odefname); odefFound = true; } if (!RoR::Application::GetCacheSystem()->checkResourceLoaded(odefname, odefgroup)) if (!odefFound) { LOG("Error while loading Terrain: could not find required .odef file: " + odefname + ". Ignoring entry."); return; } DataStreamPtr ds=ResourceGroupManager::getSingleton().openResource(odefname, odefgroup); ds->readLine(mesh, 1023); if (String(mesh) == "LOD") { // LOD line is obsolete ds->readLine(mesh, 1023); } //scale ds->readLine(line, 1023); sscanf(line, "%f, %f, %f",&sc.x, &sc.y, &sc.z); String entityName = "object" + TOSTRING(objcounter) + "(" + name + ")"; objcounter++; SceneNode *tenode = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); bool background_loading = BSETTING("Background Loading", false); MeshObject *mo = NULL; if (String(mesh) != "none") { mo = new MeshObject(mesh, entityName, tenode, NULL, background_loading); } //mo->setQueryFlags(OBJECTS_MASK); //tenode->attachObject(te); tenode->setScale(sc); tenode->setPosition(pos); tenode->rotate(rotation); tenode->pitch(Degree(-90)); tenode->setVisible(true); // register in map loadedObject_t *obj = &loadedObjects[instancename]; obj->instanceName = instancename; obj->loadType = 0; obj->enabled = true; obj->sceneNode = tenode; obj->collTris.clear(); if (mo && uniquifyMaterial && !instancename.empty()) { for (unsigned int i = 0; i < mo->getEntity()->getNumSubEntities(); i++) { SubEntity *se = mo->getEntity()->getSubEntity(i); String matname = se->getMaterialName(); String newmatname = matname + "/" + instancename; //LOG("subentity " + TOSTRING(i) + ": "+ matname + " -> " + newmatname); se->getMaterial()->clone(newmatname); se->setMaterialName(newmatname); } } //String meshGroup = ResourceGroupManager::getSingleton().findGroupContainingResource(mesh); //MeshPtr mainMesh = mo->getMesh(); //collision box(es) bool virt=false; bool rotating=false; bool classic_ref=true; // everything is of concrete by default ground_model_t *gm = gEnv->collisions->getGroundModelByString("concrete"); char eventname[256] = {}; while (!ds->eof()) { size_t ll=ds->readLine(line, 1023); // little workaround to trim it String lineStr = String(line); Ogre::StringUtil::trim(lineStr); const char* ptline = lineStr.c_str(); if (ll==0 || line[0]=='/' || line[0]==';') continue; if (!strcmp("end",ptline)) break; if (!strcmp("movable", ptline)) {ismovable=true;continue;}; if (!strcmp("localizer-h", ptline)) { localizers[free_localizer].position=Vector3(pos.x,pos.y,pos.z); localizers[free_localizer].rotation=rotation; localizers[free_localizer].type=Autopilot::LOCALIZER_HORIZONTAL; free_localizer++; continue; } if (!strcmp("localizer-v", ptline)) { localizers[free_localizer].position=Vector3(pos.x,pos.y,pos.z); localizers[free_localizer].rotation=rotation; localizers[free_localizer].type=Autopilot::LOCALIZER_VERTICAL; free_localizer++; continue; } if (!strcmp("localizer-ndb", ptline)) { localizers[free_localizer].position=Vector3(pos.x,pos.y,pos.z); localizers[free_localizer].rotation=rotation; localizers[free_localizer].type=Autopilot::LOCALIZER_NDB; free_localizer++; continue; } if (!strcmp("localizer-vor", ptline)) { localizers[free_localizer].position=Vector3(pos.x,pos.y,pos.z); localizers[free_localizer].rotation=rotation; localizers[free_localizer].type=Autopilot::LOCALIZER_VOR; free_localizer++; continue; } if (!strcmp("standard", ptline)) {classic_ref=false;tenode->pitch(Degree(90));continue;}; if (!strncmp("sound", ptline, 5)) { #ifdef USE_OPENAL if (!SoundScriptManager::getSingleton().isDisabled()) { char tmp[255]=""; sscanf(ptline, "sound %s", tmp); SoundScriptInstance *sound = SoundScriptManager::getSingleton().createInstance(tmp, MAX_TRUCKS+1, tenode); sound->setPosition(tenode->getPosition(), Vector3::ZERO); sound->start(); } #endif //USE_OPENAL continue; } if (!strcmp("beginbox", ptline) || !strcmp("beginmesh", ptline)) { dr = Vector3::ZERO; rotating=false; virt=false; forcecam=false; event_filter=EVENT_NONE; eventname[0]=0; collmesh[0]=0; gm = gEnv->collisions->getGroundModelByString("concrete"); continue; }; if (!strncmp("boxcoords", ptline, 9)) { sscanf(ptline, "boxcoords %f, %f, %f, %f, %f, %f",&l.x,&h.x,&l.y,&h.y,&l.z, &h.z); continue; } if (!strncmp("mesh", ptline, 4)) { sscanf(ptline, "mesh %s",collmesh); continue; } if (!strncmp("rotate", ptline, 6)) { sscanf(ptline, "rotate %f, %f, %f",&sr.x, &sr.y, &sr.z); rotating=true; continue; } if (!strncmp("forcecamera", ptline, 11)) { sscanf(ptline, "forcecamera %f, %f, %f",&fc.x, &fc.y, &fc.z); forcecam=true; continue; } if (!strncmp("direction", ptline, 9)) { sscanf(ptline, "direction %f, %f, %f",&dr.x, &dr.y, &dr.z); continue; } if (!strncmp("frictionconfig", ptline, 14) && strlen(ptline) > 15) { // load a custom friction config gEnv->collisions->loadGroundModelsConfigFile(String(ptline + 15)); continue; } if ((!strncmp("stdfriction", ptline, 11) || !strncmp("usefriction", ptline, 11)) && strlen(ptline) > 12) { String modelName = String(ptline + 12); gm = gEnv->collisions->getGroundModelByString(modelName); continue; } if (!strcmp("virtual", ptline)) {virt=true;continue;}; if (!strncmp("event", ptline, 5)) { char ts[256]; ts[0]=0; sscanf(ptline, "event %s %s",eventname, ts); if (!strncmp(ts, "avatar", 6)) event_filter=EVENT_AVATAR; else if (!strncmp(ts, "truck", 5)) event_filter=EVENT_TRUCK; else if (!strncmp(ts, "airplane", 8)) event_filter=EVENT_AIRPLANE; else if (!strncmp(ts, "boat", 8)) event_filter=EVENT_BOAT; else if (!strncmp(ts, "delete", 8)) event_filter=EVENT_DELETE; //if (!strncmp(ts, "shoptruck", 9)) // terrainManager->terrainHasTruckShop=true; // fallback if (strlen(ts) == 0) event_filter=EVENT_ALL; continue; } if (!strcmp("endbox", ptline)) { if (enable_collisions) { const String eventnameStr = eventname; int boxnum = gEnv->collisions->addCollisionBox(tenode, rotating, virt, pos, rot, l, h, sr, eventnameStr, instancename, forcecam, fc, sc, dr, event_filter, scripthandler); obj->collBoxes.push_back((boxnum)); } continue; } if (!strcmp("endmesh", ptline)) { gEnv->collisions->addCollisionMesh(collmesh, Vector3(pos.x,pos.y,pos.z), tenode->getOrientation(), sc, gm, &(obj->collTris)); continue; } if (!strncmp("particleSystem", ptline, 14) && tenode) { float x=0, y=0, z=0, scale=0; char pname[255]="", sname[255]=""; int res = sscanf(ptline, "particleSystem %f, %f, %f, %f, %s %s", &scale, &x, &y, &z, pname, sname); if (res != 6) continue; // hacky: prevent duplicates String paname = String(pname); while(gEnv->sceneManager->hasParticleSystem(paname)) paname += "_"; // create particle system ParticleSystem* pParticleSys = gEnv->sceneManager->createParticleSystem(paname, String(sname)); pParticleSys->setCastShadows(false); pParticleSys->setVisibilityFlags(DEPTHMAP_DISABLED); // disable particles in depthmap // Some affectors may need its instance name (e.g. for script feedback purposes) #ifdef USE_ANGELSCRIPT unsigned short affCount = pParticleSys->getNumAffectors(); ParticleAffector* pAff; for (unsigned short i = 0; i<affCount; ++i) { pAff = pParticleSys->getAffector(i); if (pAff->getType()=="ExtinguishableFire") { ((ExtinguishableFireAffector*)pAff)->setInstanceName(obj->instanceName); } } #endif // USE_ANGELSCRIPT SceneNode *sn = tenode->createChildSceneNode(); sn->attachObject(pParticleSys); sn->pitch(Degree(90)); continue; } if (!strncmp("setMeshMaterial", ptline, 15)) { char mat[256]=""; sscanf(ptline, "setMeshMaterial %s", mat); if (mo->getEntity() && strnlen(mat,250)>0) { mo->getEntity()->setMaterialName(String(mat)); // load it //MaterialManager::getSingleton().load(String(mat), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); } continue; } if (!strncmp("generateMaterialShaders", ptline, 23)) { char mat[256]=""; sscanf(ptline, "generateMaterialShaders %s", mat); if (BSETTING("Use RTShader System", false)) { Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(String(mat), Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, String(mat)); } continue; } if (!strncmp("playanimation", ptline, 13) && mo) { char animname[256]=""; float speedfactorMin = 0, speedfactorMax = 0; sscanf(ptline, "playanimation %f, %f, %s", &speedfactorMin, &speedfactorMax, animname); if (tenode && mo->getEntity() && strnlen(animname,250)>0) { AnimationStateSet *s = mo->getEntity()->getAllAnimationStates(); if (!s->hasAnimationState(String(animname))) { LOG("ODEF: animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + ".odef' not found!"); continue; } animated_object_t ao; ao.node = tenode; ao.ent = mo->getEntity(); ao.speedfactor = speedfactorMin; if (speedfactorMin != speedfactorMax) ao.speedfactor = Math::RangeRandom(speedfactorMin, speedfactorMax); ao.anim = 0; try { ao.anim = mo->getEntity()->getAnimationState(String(animname)); } catch (...) { ao.anim = 0; } if (!ao.anim) { LOG("ODEF: animation '" + String(animname) + "' for mesh: '" + String(mesh) + "' in odef file '" + name + ".odef' not found!"); continue; } ao.anim->setEnabled(true); animatedObjects.push_back(ao); } continue; } if (!strncmp("drawTextOnMeshTexture", ptline, 21) && mo) { if (!mo->getEntity()) continue; String matName = mo->getEntity()->getSubEntity(0)->getMaterialName(); MaterialPtr m = MaterialManager::getSingleton().getByName(matName); if (m.getPointer() == 0) { LOG("ODEF: problem with drawTextOnMeshTexture command: mesh material not found: "+odefname+" : "+String(ptline)); continue; } String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName(); Texture* background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer(); if (!background) { LOG("ODEF: problem with drawTextOnMeshTexture command: mesh texture not found: "+odefname+" : "+String(ptline)); continue; } static int textureNumber = 0; textureNumber++; char tmpTextName[256]="", tmpMatName[256]=""; sprintf(tmpTextName, "TextOnTexture_%d_Texture", textureNumber); sprintf(tmpMatName, "TextOnTexture_%d_Material", textureNumber); // Make sure the texture is not WRITE_ONLY, we need to read the buffer to do the blending with the font (get the alpha for example) TexturePtr texture = TextureManager::getSingleton().createManual(tmpTextName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (Ogre::uint)background->getWidth(), (Ogre::uint)background->getHeight(), MIP_UNLIMITED , PF_X8R8G8B8, Ogre::TU_STATIC|Ogre::TU_AUTOMIPMAP, new ResourceBuffer()); if (texture.getPointer() == 0) { LOG("ODEF: problem with drawTextOnMeshTexture command: could not create texture: "+odefname+" : "+String(ptline)); continue; } float x=0, y=0, w=0, h=0; float a=0, r=0, g=0, b=0; char fontname[256]=""; char text[256]=""; char option='l'; int res = sscanf(ptline, "drawTextOnMeshTexture %f, %f, %f, %f, %f, %f, %f, %f, %c, %s %s", &x, &y, &w, &h, &r, &g, &b, &a, &option, fontname, text); if (res < 11) { LOG("ODEF: problem with drawTextOnMeshTexture command: "+odefname+" : "+String(ptline)); continue; } // check if we got a template argument if (!strncmp(text, "{{argument1}}", 13)) strncpy(text, instancename.c_str(), 250); // replace '_' with ' ' char *text_pointer = text; while (*text_pointer!=0) {if (*text_pointer=='_') *text_pointer=' ';text_pointer++;}; Font* font = (Font *)FontManager::getSingleton().getByName(String(fontname)).getPointer(); if (!font) { LOG("ODEF: problem with drawTextOnMeshTexture command: font not found: "+odefname+" : "+String(ptline)); continue; } //Draw the background to the new texture texture->getBuffer()->blit(background->getBuffer()); x = background->getWidth() * x; y = background->getHeight() * y; w = background->getWidth() * w; h = background->getHeight() * h; Image::Box box = Image::Box((size_t)x, (size_t)y, (size_t)(x+w), (size_t)(y+h)); WriteToTexture(String(text), texture, box, font, ColourValue(r, g, b, a), option); // we can save it to disc for debug purposes: //SaveImage(texture, "test.png"); m->clone(tmpMatName); MaterialPtr mNew = MaterialManager::getSingleton().getByName(tmpMatName); mNew->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(tmpTextName); mo->getEntity()->setMaterialName(String(tmpMatName)); continue; } LOG("ODEF: unknown command in "+odefname+" : "+String(ptline)); } //add icons if type is set #ifdef USE_MYGUI String typestr = ""; if (!type.empty() && gEnv->surveyMap) { typestr = type; // hack for raceways if (name == "chp-checkpoint") typestr = "checkpoint"; if (name == "chp-start") typestr = "racestart"; if (name == "road", 4) typestr = "road"; if (typestr != "" && typestr != "road" && typestr != "sign") { SurveyMapEntity *e = gEnv->surveyMap->createMapEntity(typestr); if (e) { e->setVisibility(true); e->setPosition(pos); e->setRotation(Radian(rot.y)); if (!name.empty()) e->setDescription(instancename); } } } #endif //USE_MYGUI }