//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames // Copyright (C) 2015 Faust Logic, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. // //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// #include "afx/arcaneFX.h" #include "afx/afxEffectWrapper.h" #include "afx/afxChoreographer.h" #include "afx/xm/afxXfmMod.h" //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// class afxXM_MountedImageNodeData : public afxXM_BaseData { typedef afxXM_BaseData Parent; public: StringTableEntry node_name; // name of a mounted-image node U32 image_slot; // which mounted-image? // (0 <= image_slot < MaxMountedImages) public: /*C*/ afxXM_MountedImageNodeData(); /*C*/ afxXM_MountedImageNodeData(const afxXM_MountedImageNodeData&, bool = false); void packData(BitStream* stream); void unpackData(BitStream* stream); bool onAdd(); virtual bool allowSubstitutions() const { return true; } static void initPersistFields(); afxXM_Base* create(afxEffectWrapper* fx, bool on_server); DECLARE_CONOBJECT(afxXM_MountedImageNodeData); DECLARE_CATEGORY("AFX"); }; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// class afxXM_MountedImageNode : public afxXM_Base { typedef afxXM_Base Parent; StringTableEntry mNode_name; U32 mImage_slot; S32 mNode_ID; ShapeBase* mShape; afxConstraint* mCons; afxConstraint* find_constraint(); public: /*C*/ afxXM_MountedImageNode(afxXM_MountedImageNodeData*, afxEffectWrapper*); virtual void start(F32 timestamp); virtual void updateParams(F32 dt, F32 elapsed, afxXM_Params& params); }; //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// IMPLEMENT_CO_DATABLOCK_V1(afxXM_MountedImageNodeData); ConsoleDocClass( afxXM_MountedImageNodeData, "@brief An xmod datablock.\n\n" "@ingroup afxXMods\n" "@ingroup AFX\n" "@ingroup Datablocks\n" ); afxXM_MountedImageNodeData::afxXM_MountedImageNodeData() { image_slot = 0; node_name = ST_NULLSTRING; } afxXM_MountedImageNodeData::afxXM_MountedImageNodeData(const afxXM_MountedImageNodeData& other, bool temp_clone) : afxXM_BaseData(other, temp_clone) { image_slot = other.image_slot; node_name = other.node_name; } void afxXM_MountedImageNodeData::initPersistFields() { addField("imageSlot", TypeS32, Offset(image_slot, afxXM_MountedImageNodeData), "..."); addField("nodeName", TypeString, Offset(node_name, afxXM_MountedImageNodeData), "..."); Parent::initPersistFields(); } void afxXM_MountedImageNodeData::packData(BitStream* stream) { Parent::packData(stream); stream->write(image_slot); stream->writeString(node_name); } void afxXM_MountedImageNodeData::unpackData(BitStream* stream) { Parent::unpackData(stream); stream->read(&image_slot); node_name = stream->readSTString(); } bool afxXM_MountedImageNodeData::onAdd() { if (Parent::onAdd() == false) return false; if (image_slot >= ShapeBase::MaxMountedImages) { // datablock will not be added if imageSlot is out-of-bounds Con::errorf(ConsoleLogEntry::General, "afxXM_MountedImageNodeData(%s): imageSlot (%u) >= MaxMountedImages (%d)", getName(), image_slot, ShapeBase::MaxMountedImages); return false; } return true; } afxXM_Base* afxXM_MountedImageNodeData::create(afxEffectWrapper* fx, bool on_server) { afxXM_MountedImageNodeData* datablock = this; if (getSubstitutionCount() > 0) { datablock = new afxXM_MountedImageNodeData(*this, true); this->performSubstitutions(datablock, fx->getChoreographer(), fx->getGroupIndex()); } return new afxXM_MountedImageNode(datablock, fx); } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~// afxXM_MountedImageNode::afxXM_MountedImageNode(afxXM_MountedImageNodeData* db, afxEffectWrapper* fxw) : afxXM_Base(db, fxw) { mImage_slot = db->image_slot; mNode_name = db->node_name; mCons = 0; mNode_ID = -1; mShape = 0; } // find the first constraint with a shape by checking pos // then orient constraints in that order. afxConstraint* afxXM_MountedImageNode::find_constraint() { afxConstraint* cons = fx_wrapper->getOrientConstraint(); if (cons && dynamic_cast(cons->getSceneObject())) return cons; cons = fx_wrapper->getPosConstraint(); if (cons && dynamic_cast(cons->getSceneObject())) return cons; return 0; } void afxXM_MountedImageNode::start(F32 timestamp) { // constraint won't change over the modifier's // lifetime so we find it here in start(). mCons = find_constraint(); if (!mCons) Con::errorf(ConsoleLogEntry::General, "afxXM_MountedImageNode: failed to find a ShapeBase derived constraint source."); } void afxXM_MountedImageNode::updateParams(F32 dt, F32 elapsed, afxXM_Params& params) { if (!mCons) return; // validate shape // The shape must be validated in case it gets deleted // of goes out scope. SceneObject* scene_object = mCons->getSceneObject(); if (scene_object != (SceneObject*)mShape) { mShape = dynamic_cast(scene_object); if (mShape && mNode_name != ST_NULLSTRING) { mNode_ID = mShape->getNodeIndex(mImage_slot, mNode_name); if (mNode_ID < 0) { Con::errorf(ConsoleLogEntry::General, "afxXM_MountedImageNode: failed to find nodeName, \"%s\".", mNode_name); } } else mNode_ID = -1; } if (mShape) { mShape->getImageTransform(mImage_slot, mNode_ID, ¶ms.ori); params.pos = params.ori.getPosition(); } } //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//