/* Crystal Space Entity Layer Copyright (C) 2003 by Jorrit Tyberghein This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "cssysdef.h" #include "csutil/eventnames.h" #include "iutil/objreg.h" #include "iutil/eventq.h" #include "iutil/vfs.h" #include "csutil/scfstringarray.h" #include "ivaria/reporter.h" #include "iengine/engine.h" #include "iengine/mesh.h" #include "iengine/movable.h" #include "iengine/sector.h" #include "ivideo/graph3d.h" #include "physicallayer/pl.h" #include "physicallayer/entity.h" #include "physicallayer/propclas.h" #include "propclass/mesh.h" #include "propclass/meshsel.h" #include "propclass/tooltip.h" #include "propclass/camera.h" #include "propclass/inv.h" #include "propclass/gravity.h" #include "propclass/timer.h" #include "propclass/region.h" #include "propclass/prop.h" #include "propclass/rules.h" #include "propclass/billboard.h" #include "plugins/behaviourlayer/xml/blxml.h" #include "plugins/behaviourlayer/xml/behave_xml.h" #include "plugins/behaviourlayer/xml/xmlscript.h" //--------------------------------------------------------------------------- SCF_IMPLEMENT_IBASE (celBehaviourXml) SCF_IMPLEMENTS_INTERFACE (iCelBehaviour) SCF_IMPLEMENT_IBASE_END csRandomGen celBehaviourXml::rng (1234567); celBehaviourXml::celBehaviourXml (iCelEntity* entity, iObjectRegistry* object_reg) { SCF_CONSTRUCT_IBASE (0); celBehaviourXml::entity = entity; celBehaviourXml::object_reg = object_reg; name = 0; script = 0; } iPcBillboard* celBehaviourXml::GetBillboard () { if (!billboard) { csRef b = CEL_QUERY_PROPCLASS_ENT (entity, iPcBillboard); if (!b) { csRef pl = CS_QUERY_REGISTRY (object_reg, iCelPlLayer); iCelPropertyClass* pc = pl->CreatePropertyClass (entity, "pcbillboard"); if (pc) b = SCF_QUERY_INTERFACE (pc, iPcBillboard); } billboard = b; } return billboard; } iPcRules* celBehaviourXml::GetRules () { if (!rules) { csRef p = CEL_QUERY_PROPCLASS_ENT (entity, iPcRules); if (!p) { csRef pl = CS_QUERY_REGISTRY (object_reg, iCelPlLayer); iCelPropertyClass* pc = pl->CreatePropertyClass (entity, "pcrules"); if (pc) p = SCF_QUERY_INTERFACE (pc, iPcRules); } rules = p; } return rules; } iPcProperties* celBehaviourXml::GetProperties () { if (!props) { csRef p; p = CEL_QUERY_PROPCLASS (entity->GetPropertyClassList (), iPcProperties); if (!p) { csRef pl = CS_QUERY_REGISTRY (object_reg, iCelPlLayer); iCelPropertyClass* pc = pl->CreatePropertyClass (entity, "pcproperties"); if (pc) p = SCF_QUERY_INTERFACE (pc, iPcProperties); } props = p; } return props; } celBehaviourXml::~celBehaviourXml () { delete[] name; SCF_DESTRUCT_IBASE (); } bool celBehaviourXml::SendMessage (const char* msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, ...) { va_list arg; va_start (arg, params); bool rc = SendMessageV (msg_id, pc, ret, params, arg); va_end (arg); return rc; } bool celBehaviourXml::SendMessageV (const char* msg_id, iCelPropertyClass* /*pc*/, celData& ret, iCelParameterBlock* params, va_list arg) { ret.Set ((int32)-1); celBlXml* cbl = (celBlXml*)bl; celXmlScriptEventHandler* h = script->GetEventHandler (msg_id); if (h) { cbl->call_stack.Push (msg_id); cbl->call_stack_params.Push (params); cbl->call_stack_entity.Push (entity); #if DO_PROFILE csString msg = script->GetName (); msg += '/'; msg += msg_id; int idx = cbl->profile_info_hash.Get ((const char*)msg); if (idx == 0) { idx = cbl->profile_info.Push (celBlXml::celProfileInfo ()); celBlXml::celProfileInfo& pi = cbl->profile_info[idx]; pi.msg = csStrNew ((const char*)msg); pi.time = 0; pi.count = 0; cbl->profile_info_hash.Put (pi.msg, idx+1); } else idx--; csTicks start = csGetTicks (); #endif h->Execute (entity, cbl, this, ret, params); #if DO_PROFILE csTicks stop = csGetTicks (); celBlXml::celProfileInfo& pi = cbl->profile_info[idx]; pi.time += stop-start; pi.count++; #endif cbl->call_stack_entity.Pop (); cbl->call_stack_params.Pop (); cbl->call_stack.Pop (); } else { // Check the superscript if there is one. celXmlScript* superscript = script->GetSuperScript (); while (superscript) { h = superscript->GetEventHandler (msg_id); if (h) { cbl->call_stack.Push (msg_id); cbl->call_stack_params.Push (params); cbl->call_stack_entity.Push (entity); #if DO_PROFILE csString msg = superscript->GetName (); msg += '/'; msg += msg_id; int idx = cbl->profile_info_hash.Get ((const char*)msg); if (idx == 0) { idx = cbl->profile_info.Push (celBlXml::celProfileInfo ()); celBlXml::celProfileInfo& pi = cbl->profile_info[idx]; pi.msg = csStrNew ((const char*)msg); pi.time = 0; pi.count = 0; cbl->profile_info_hash.Put (pi.msg, idx+1); } else idx--; csTicks start = csGetTicks (); #endif h->Execute (entity, cbl, this, ret, params); #if DO_PROFILE csTicks stop = csGetTicks (); celBlXml::celProfileInfo& pi = cbl->profile_info[idx]; pi.time += stop-start; pi.count++; #endif cbl->call_stack_entity.Pop (); cbl->call_stack_params.Pop (); cbl->call_stack.Pop (); break; } else { superscript = superscript->GetSuperScript (); } } } return h != 0; } void celBehaviourXml::Quit () { csRef q = csQueryRegistry (object_reg); q->GetEventOutlet ()->Broadcast (csevQuit (object_reg)); } //--------------------------------------------------------------------------- SCF_IMPLEMENT_IBASE (celBehaviourBootstrap) SCF_IMPLEMENTS_INTERFACE (iCelBehaviour) SCF_IMPLEMENT_IBASE_END celBehaviourBootstrap::celBehaviourBootstrap (iCelEntity* entity, iObjectRegistry* object_reg) { SCF_CONSTRUCT_IBASE (0); celBehaviourBootstrap::entity = entity; celBehaviourBootstrap::object_reg = object_reg; name = 0; } celBehaviourBootstrap::~celBehaviourBootstrap () { delete[] name; SCF_DESTRUCT_IBASE (); } bool celBehaviourBootstrap::SendMessage (const char* msg_id, iCelPropertyClass* pc, celData& ret, iCelParameterBlock* params, ...) { va_list arg; va_start (arg, params); bool rc = SendMessageV (msg_id, pc, ret, params, arg); va_end (arg); return rc; } bool celBehaviourBootstrap::SendMessageV (const char* msg_id, iCelPropertyClass* /*pc*/, celData&, iCelParameterBlock* params, va_list arg) { csRef pl = CS_QUERY_REGISTRY (object_reg, iCelPlLayer); if (!strcmp (msg_id, "load")) { csString path,worldname; if (params) { const celData* cd; cd = params->GetParameter ( pl->FetchStringID ("cel.parameter.parameter1")); if (cd) path = csString(((iString const *)(cd->value.s))->GetData()); cd = params->GetParameter ( pl->FetchStringID ("cel.parameter.parameter2")); if (cd) worldname = csString(((iString const *)(cd->value.s))->GetData()); } printf ("path=%s\n", path.GetData()); fflush (stdout); printf ("worldname=%s\n", worldname.GetData()); fflush (stdout); pl->LoadPropertyClassFactory ("cel.pcfactory.region"); pl->LoadPropertyClassFactory ("cel.pcfactory.defaultcamera"); iCelPropertyClass* pc; csRef pccamera; pc = pl->CreatePropertyClass (entity, "pcdefaultcamera"); if (!pc) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.cel.behaviour.xml", "Couldn't create 'pccamera' property class!"); return false; } pccamera = SCF_QUERY_INTERFACE (pc, iPcCamera); //pccamera->SetMode (iPcCamera::firstperson); csRef pcregion; pc = pl->CreatePropertyClass (entity, "pcregion"); if (!pc) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.cel.behaviour.xml", "Couldn't create 'pcregion' property class!"); return false; } // find path csStringArray paths; paths.Push ("/lev/"); csRef VFS = CS_QUERY_REGISTRY (object_reg, iVFS); VFS->PushDir (); if (!VFS->ChDirAuto (path.GetData(),&paths,0,worldname.GetData())) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.cel.behaviour.xml", "Error setting directory '%s'!",path.GetData()); VFS->PopDir (); return false; } // get back the path we mounted and get out path=VFS->GetCwd(); VFS->PopDir (); // load with pcregion pcregion = SCF_QUERY_INTERFACE (pc, iPcRegion); pcregion->SetWorldFile (path, worldname); pcregion->SetRegionName (worldname); if (!pcregion->Load ()) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.cel.behaviour.xml", "Couldn't load '%s' at '%s'!", worldname.GetData(), path.GetData()); return false; } pccamera->SetRegion (pcregion); return true; } return false; } //---------------------------------------------------------------------------