void GuiGameListMenuCtrl::changeRow(S32 delta) { S32 oldRowIndex = getSelected(); S32 newRowIndex = oldRowIndex; do { newRowIndex += delta; if (newRowIndex >= mRows.size()) { newRowIndex = 0; } else if (newRowIndex < 0) { newRowIndex = mRows.size() - 1; } } while ((! mRows[newRowIndex]->mEnabled) && (newRowIndex != oldRowIndex)); setSelected(newRowIndex); // do the callback if it is defined StringTableEntry onChange = StringTable->insert("onChange", false); if (isMethod(onChange)) { Con::executef(this, onChange); } }
bool Item::isCallable() const { if ( isClass() || isFunction() || isMethod() ) return true; if( isObject() ) { return asObjectSafe()->hasProperty( OVERRIDE_OP_CALL ); } //a bit more complex: a callable array... if( type() == FLC_ITEM_ARRAY ) { CoreArray& arr = *asArray(); if ( arr.length() > 0 ) { // avoid infinite recursion. // even if arr[0] is not an array, the check is harmless, as we check by ptr value. return arr[0].asArray() != &arr && arr[0].isCallable(); } } // in all the other cases, the item is not callable return false; }
/** * Static method used for constructing new method objects in * various contexts (such as the define method on the Class class). * * @param pgmname The name of the method we're creating. * @param source The method source (either a string or an array). * @param scope The scope that the new method object will be given. * @param position The position used for reporting errors. This is the position * of the source argument for the calling method context. * * @return The constructed method object. */ MethodClass *MethodClass::newMethodObject(RexxString *pgmname, RexxObject *source, RexxClass *scope, const char *position) { // this is used in contexts where an existing method object is allowed...perform this // check here and just return the original object if it is already a method. if (isMethod(source)) { return ((MethodClass *)source)->newScope(scope); } // validate, and potentially transform, the method source object. ArrayClass *newSourceArray = processExecutableSource(source, position); // if not a valid source, give an error if (newSourceArray == OREF_NULL) { reportException(Error_Incorrect_method_no_method_type, position); } // this method is called when methods are added to class, object, directory, etc. // we want to inherit from the current execution source context if we can. PackageClass *sourceContext = OREF_NULL; // see if we have an active context and use the current source as the basis for the lookup RexxActivation *currentContext = ActivityManager::currentActivity->getCurrentRexxFrame(); if (currentContext != OREF_NULL) { sourceContext = currentContext->getPackage(); } // create a method and give it the target scope MethodClass *method = LanguageParser::createMethod(pgmname, newSourceArray, sourceContext); method->setScope(scope); return method; }
void GuiDecalEditorCtrl::deleteSelectedDecal() { if ( !mSELDecal ) return; // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. DIDeleteUndoAction *action = new DIDeleteUndoAction("Delete Decal"); action->deleteDecal( *mSELDecal ); action->mEditor = this; // Submit it. undoMan->addAction( action ); if ( isMethod( "onDeleteInstance" ) ) { char buffer[512]; dSprintf(buffer, 512, "%i", mSELDecal->mId); Con::executef( this, "onDeleteInstance", String(buffer).c_str(), mSELDecal->mDataBlock->lookupName.c_str() ); } gDecalManager->removeDecal( mSELDecal ); mSELDecal = NULL; }
Function::Function(const std::string& decl, NameSpace* pNameSpace): Decl(decl, pNameSpace), _flags(0), _retParam() { if (hasAttr(decl, "static")) _flags |= FN_STATIC; if (hasAttr(decl, "virtual")) _flags |= FN_VIRTUAL; if (hasAttr(decl, "inline")) _flags |= FN_INLINE; if (hasAttr(decl, "template")) _flags |= FN_TEMPLATE; if (isMethod() || isFunction()) { // parse the decl std::size_t pos = decl.rfind(name()); _retParam = decl.substr(0, pos-1); // eliminate static, virtual, inline, template _retParam = replace(_retParam, "static ", ""); _retParam = replace(_retParam, "virtual ", ""); _retParam = replace(_retParam, "inline ", ""); if (_flags & FN_TEMPLATE) { std::size_t pos = _retParam.find(">"); poco_assert (pos != std::string::npos); _retParam = _retParam.substr(pos+1); } Poco::trimInPlace(_retParam); } }
//----------------------------------------------------------- // Function name: SimComponent::handlesConsoleMethod // Summary: //----------------------------------------------------------- bool DynamicConsoleMethodComponent::handlesConsoleMethod( const char *fname, S32 *routingId ) { // CodeReview: Host object is now given priority over components for method // redirection. [6/23/2007 Pat] // On this object? if( isMethod( fname ) ) { *routingId = -1; // -1 denotes method on object return true; } // on this objects components? S32 nI = 0; VectorPtr<SimComponent*> &componentList = lockComponentList(); for( SimComponentIterator nItr = componentList.begin(); nItr != componentList.end(); nItr++, nI++ ) { SimObject *pComponent = dynamic_cast<SimObject*>(*nItr); if( pComponent != NULL && pComponent->isMethod( fname ) ) { *routingId = -2; // -2 denotes method on component unlockComponentList(); return true; } } unlockComponentList(); return false; }
std::size_t FunctionAttributes::hash() const { Hasher hasher; hasher.add(isVarArg()); hasher.add(isMethod()); hasher.add(isTemplated()); hasher.add(noExceptPredicate()); return hasher.get(); }
void GuiScriptNotifyCtrl::childResized(GuiScriptNotifyCtrl *child) { Parent::childResized( child ); // Call Script. if( mOnChildResized && isMethod( "onChildResized" ) ) Con::executef(this, "onChildResized", child->getIdString() ); }
void GuiScriptNotifyCtrl::setFirstResponder() { Parent::setFirstResponder(); // Call Script. if( mOnGainFirstResponder && isFirstResponder() && isMethod( "onGainFirstResponder" ) ) Con::executef(this, "onGainFirstResponder" ); }
var var::invokeMethod (DynamicObject* const target, const var* const arguments, const int numArguments) const { jassert (target != nullptr); if (isMethod()) return (target->*(value.methodValue)) (arguments, numArguments); return var::null; }
// virtual QModelIndex CQTaskMethodParametersDM::parent(const QModelIndex & index) const { CCopasiParameter * pNode = nodeFromIndex(index); if (pNode == NULL || isMethod(pNode)) { return QModelIndex(); } if (isMethod(dynamic_cast<CCopasiParameter *>(pNode->getObjectParent()))) { return QModelIndex(); } CCopasiParameter * pParent = static_cast< CCopasiParameter * >(pNode->getObjectParent()); return createIndex(getRow(pParent), 0, pParent); }
void GuiScriptNotifyCtrl::parentResized(const RectI &oldParentRect, const RectI &newParentRect) { Parent::parentResized( oldParentRect, newParentRect ); // Call Script. if( mOnParentResized && isMethod( "onParentResized" ) ) Con::executef(this, "onParentResized" ); }
std::string FunctionAttributes::toString() const { return makeString("FunctionAttributes(" "isVarArg: %s, " "isMethod: %s, " "isTemplated: %s, " "noExceptPredicate: %s)", isVarArg() ? "true" : "false", isMethod() ? "true" : "false", isTemplated() ? "true" : "false", noExceptPredicate().toString().c_str()); }
bool GuiScriptNotifyCtrl::resize(const Point2I &newPosition, const Point2I &newExtent) { if( !Parent::resize( newPosition, newExtent ) ) return false; // Call Script. if( mOnResize && isMethod( "onResize" ) ) Con::executef(this, "onResize" ); return true; }
const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const { if (isMethod()) { DynamicObject* const target = targetObject.getObject(); if (target != 0) return (target->*(value.methodValue)) (arguments, numArguments); } return var::null; }
int CQTaskMethodParametersDM::getRow(const CCopasiParameter * pNode) const { if (pNode == NULL) { return -1; } CCopasiParameterGroup * pParent = static_cast< CCopasiParameterGroup * >(pNode->getObjectParent()); if (pParent == NULL) { return 0; } if (isMethod(pParent)) { QVector< CCopasiMethod * >::const_iterator itMethod = mMethods.constBegin(); QVector< CCopasiMethod * >::const_iterator endMethod = mMethods.constEnd(); int i = 0; for (; itMethod != endMethod; ++itMethod) { CCopasiParameterGroup::index_iterator it = pParent->beginIndex(); CCopasiParameterGroup::index_iterator end = pParent->endIndex(); for (; it != end; ++it, ++i) if (*it == pNode) { return i; } } } else { int i = 0; CCopasiParameterGroup::index_iterator it = pParent->beginIndex(); CCopasiParameterGroup::index_iterator end = pParent->endIndex(); for (; it != end; ++it, ++i) if (*it == pNode) { return i; } } return -1; }
QModelIndex CQTaskMethodParametersDM::index(CCopasiParameter * pNode) const { if (pNode == NULL) { return QModelIndex(); } if (isMethod(pNode)) { return index(0, 0, QModelIndex()); } QModelIndex Parent = index(static_cast< CCopasiParameter * >(pNode->getObjectParent())); return index(getRow(pNode), 0, Parent); }
fbstring PhpFunc::getCppSig() const { std::ostringstream out; fbstring nm = getCppName(); fbstring lowername = nm; std::transform(nm.begin(), nm.end(), lowername.begin(), std::ptr_fun<int, int>(std::tolower)); if (!isMethod()) { out << "HPHP::f_" << lowername << "("; } else { if (isStatic()) { out << "HPHP::c_" << className() << "::ti_" << lowername << "("; } else { out << "HPHP::c_" << className() << "::t_" << lowername << "("; } } bool firstParam = true; if (isVarArgs()) { if (!firstParam) { out << ", "; } out << "int"; firstParam = false; } for (auto const& param : m_params) { if (!firstParam) { out << ", "; } out << param.getCppType(); firstParam = false; } if (isVarArgs()) { assert(!firstParam); out << ", HPHP::Array const&"; } out << ")"; return out.str(); }
//------------------------------------------------------------------------------ //void GuiPopUpTextListCtrl::onCellSelected( Point2I /*cell*/ ) //{ // // Do nothing, the parent control will take care of everything... //} void GuiPopupTextListCtrl::onCellSelected( Point2I cell ) { // The old function is above. This new one will only call the the select // functions if we were not cancelled by a background click. // Check if we were cancelled by the user clicking on the Background ie: anywhere // other than within the text list. if(mPopUpCtrl->mBackgroundCancel) return; if( isMethod( "onSelect" ) ) Con::executef(this, "onSelect", Con::getFloatArg(cell.x), Con::getFloatArg(cell.y)); //call the console function execConsoleCallback(); //if (mConsoleCommand[0]) // Con::evaluate(mConsoleCommand, false); }
Function* Function::getOverridden() const { if (isMethod() && !(_flags & FN_STATIC)) { Struct* pClass = dynamic_cast<Struct*>(nameSpace()); if (pClass) { for (Struct::BaseIterator it = pClass->baseBegin(); it != pClass->baseEnd(); ++it) { if (it->pClass) { Function* pOverridden = it->pClass->findFunction(signature()); if (pOverridden && pOverridden->isVirtual()) return pOverridden; } } } } return 0; }
bool SimComponent::callMethodOnComponents( U32 argc, const char* argv[], const char** result ) { const char *cbName = StringTable->insert(argv[0]); if (isEnabled()) { if(isMethod(cbName)) { // This component can handle the given method *result = Con::execute( this, argc, argv, true ); return true; } else if( getComponentCount() > 0 ) { // Need to try the component's children bool handled = false; VectorPtr<SimComponent *>&componentList = lockComponentList(); for( SimComponentIterator nItr = (componentList.end()-1); nItr >= componentList.begin(); nItr-- ) { argv[0] = cbName; SimComponent *pComponent = (*nItr); AssertFatal( pComponent, "SimComponent::callMethodOnComponents - NULL component in list!" ); // Call on children handled = pComponent->callMethodOnComponents( argc, argv, result ); if (handled) break; } unlockComponentList(); if (handled) return true; } } return false; }
bool Item::canBeMethod() const { if ( isFunction() || isMethod() ) return true; //a bit more complex: a callable array... if( type() == FLC_ITEM_ARRAY ) { CoreArray& arr = *asArray(); if ( ! arr.canBeMethod() ) return false; if ( arr.length() > 0 ) { // avoid infinite recursion. // even if arr[0] is not an array, the check is harmless, as we check by ptr value. return arr[0].asArray() != &arr && arr[0].isCallable(); } } // in all the other cases, the item is not callable return false; }
bool HTTPParser::parse(HTTPRequest &request) { static const string delim = "\r\n\r\n"; int pos = m_buf.find(delim); if (pos == string::npos) return false; string data = m_buf.substr(0, pos); m_buf.erase(0, pos + delim.length()); vector<string> lines = move(Utils::Strings::split(data, "\r\n")); vector<string> parts = move(Utils::Strings::split(lines[0])); if (parts.size() != 3) throw HTTPIncompleteRequest(Utils::Strings::format("Invalid HTTP request \"%s\"", lines[0].c_str())); string method = parts[0]; if (!isMethod(method)) throw HTTPInvalidMethod(Utils::Strings::format("Invalid HTTP method \"%s\"", method.c_str())); string uri = parts[1]; map<string, string> params; parseURI(uri, params); string version = parts[2]; if (version != "HTTP/1.1") throw HTTPUnsupportedVersion(Utils::Strings::format("Unsupported HTTP version \"%s\"", version.c_str())); request = HTTPRequest(method, uri, version, params); return true; }
fbstring PhpFunc::getPrefixedCppName(bool fullyQualified /* = true */) const { std::ostringstream out; fbstring nm = getCppName(); fbstring lowername = nm; std::transform(nm.begin(), nm.end(), lowername.begin(), std::ptr_fun<int, int>(std::tolower)); if (fullyQualified) { out << "HPHP::"; } if (!isMethod()) { out << "f_" << lowername; } else { if (isStatic()) { out << "c_" << className() << "::ti_" << lowername; } else { out << "c_" << className() << "::t_" << lowername; } } return out.str(); }
void CollisionComponent::processTick() { if (!isActive()) return; //ProcessTick is where our collision testing begins! //callback if we have a persisting contact if (mContactInfo.contactObject) { if (mContactInfo.contactTimer > 0) { if (isMethod("updateContact")) Con::executef(this, "updateContact"); if (mOwner->isMethod("updateContact")) Con::executef(mOwner, "updateContact"); } ++mContactInfo.contactTimer; } else if (mContactInfo.contactTimer != 0) mContactInfo.clear(); }
PhpFunc::PhpFunc(const folly::dynamic& d, const fbstring& className) : m_idlName(d["name"].asString()), m_phpName(toPhpName(m_idlName)), m_cppName(toCppName(m_idlName)), m_className(className), m_func(d), m_desc(getFollyDynamicDefaultString(d, "desc", "")), m_returnRef(d.getDefault("ref", "false") == "true"), m_returnKindOf(KindOfNull), m_returnCppType("void"), m_returnPhpType("void"), m_minNumParams(0), m_numTypeChecks(0) { if (isMethod() && m_idlName.find_last_of(NAMESPACE_STRING) != std::string::npos) { throw std::logic_error( folly::format("'{0}' is a method and cannot have a namespace in its name", m_idlName).str() ); } auto returnIt = d.find("return"); if (returnIt != d.items().end()) { auto retNode = returnIt->second; auto typeIt = retNode.find("type"); if (typeIt != retNode.items().end()) { auto type = typeIt->second; if ((type.isString()) && (type != "void") && (type != "null")) { m_returnKindOf = m_returnRef ? KindOfRef : kindOfFromDynamic(type); m_returnCppType = typeString(type, true); m_returnPhpType = phpTypeFromDataType(m_returnKindOf); } } m_returnDesc = getFollyDynamicDefaultString(retNode, "desc", ""); } auto args = d.find("args"); if (args == d.items().end() || !args->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'args'", m_idlName).str() ); } auto ret = d.find("return"); if (ret == d.items().end() || !ret->second.isObject() || ret->second.find("type") == ret->second.items().end()) { throw std::logic_error( folly::format("'{0}' must have an array field 'return', which must have " "a string field 'type'", m_idlName).str() ); } bool magic = isMagicMethod(); m_flags = parseFlags(m_func["flags"]); ParamMode paramMode = ParamMode::CoerceAndCall; if (m_flags & ParamCoerceModeNull) { paramMode = ParamMode::ZendNull; } else if (m_flags & ParamCoerceModeFalse) { paramMode = ParamMode::ZendFalse; } for (auto &p : args->second) { PhpParam param(p, magic, paramMode); m_params.push_back(param); if (!param.hasDefault()) { ++m_minNumParams; } if (param.isCheckedType()) { ++m_numTypeChecks; } } }
void GuiDecalEditorCtrl::deleteDecalDatablock( String lookupName ) { DecalData * datablock = dynamic_cast<DecalData*> ( Sim::findObject(lookupName.c_str()) ); if( !datablock ) return; // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. DBDeleteUndoAction *action = new DBDeleteUndoAction("Delete Decal Datablock"); action->mEditor = this; action->mDatablockId = datablock->getId(); Vector<DecalInstance*> mDecalQueue; Vector<DecalInstance *>::iterator iter; mDecalQueue.clear(); const Vector<DecalSphere*> &grid = gDecalManager->getDecalDataFile()->getSphereList(); for ( U32 i = 0; i < grid.size(); i++ ) { const DecalSphere *decalSphere = grid[i]; mDecalQueue.merge( decalSphere->mItems ); } for ( iter = mDecalQueue.begin();iter != mDecalQueue.end();iter++ ) { if( !(*iter) ) continue; if( (*iter)->mDataBlock->lookupName.compare( lookupName ) == 0 ) { if( (*iter)->mId != -1 ) { //make sure to call onDeleteInstance as well if ( isMethod( "onDeleteInstance" ) ) { char buffer[512]; dSprintf(buffer, 512, "%i", (*iter)->mId); Con::executef( this, "onDeleteInstance", String(buffer).c_str(), (*iter)->mDataBlock->lookupName.c_str() ); } action->deleteDecal( *(*iter) ); if( mSELDecal == (*iter) ) mSELDecal = NULL; if( mHLDecal == (*iter) ) mHLDecal = NULL; } gDecalManager->removeDecal( (*iter) ); } } undoMan->addAction( action ); mCurrentDecalData = NULL; }
void GuiDecalEditorCtrl::on3DMouseDragged(const Gui3DMouseEvent & event) { if ( !mSELDecal ) return; // Doing a drag copy of the decal? if ( event.modifier & SI_SHIFT && !mPerformedDragCopy ) { mPerformedDragCopy = true; DecalInstance *newDecal = gDecalManager->addDecal( mSELDecal->mPosition, mSELDecal->mNormal, 0.0f, mSELDecal->mDataBlock, 1.0f, -1, PermanentDecal | SaveDecal ); newDecal->mTangent = mSELDecal->mTangent; newDecal->mSize = mSELDecal->mSize; newDecal->mTextureRectIdx = mSELDecal->mTextureRectIdx; // TODO: This is crazy... we should move this sort of tracking // inside of the decal manager... IdDecal flag maybe or just a // byproduct of PermanentDecal? // newDecal->mId = gDecalManager->mDecalInstanceVec.size(); gDecalManager->mDecalInstanceVec.push_back( newDecal ); selectDecal( newDecal ); // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( Sim::findObject( "EUndoManager", undoMan ) ) { // Create the UndoAction. DICreateUndoAction *action = new DICreateUndoAction("Create Decal"); action->addDecal( *mSELDecal ); action->mEditor = this; undoMan->addAction( action ); if ( isMethod( "onCreateInstance" ) ) { char buffer[512]; dSprintf( buffer, 512, "%i", mSELDecal->mId ); Con::executef( this, "onCreateInstance", buffer, mSELDecal->mDataBlock->lookupName.c_str()); } } } // Update the Gizmo. if (mGizmo->getSelection() != Gizmo::None) { mGizmo->on3DMouseDragged( event ); // Pull out the Gizmo transform // and position. const MatrixF &gizmoMat = mGizmo->getTransform(); const Point3F &gizmoPos = gizmoMat.getPosition(); // Get the new projection vector. VectorF upVec, rightVec; gizmoMat.getColumn( 0, &rightVec ); gizmoMat.getColumn( 2, &upVec ); const Point3F &scale = mGizmo->getScale(); // Assign the appropriate changed value back to the decal. if ( mGizmo->getMode() == ScaleMode ) { // Save old size. const F32 oldSize = mSELDecal->mSize; // Set new size. mSELDecal->mSize = ( scale.x + scale.y ) * 0.5f; // See if the decal properly clips/projects at this size. If not, // stick to the old size. mSELEdgeVerts.clear(); if ( !gDecalManager->clipDecal( mSELDecal, &mSELEdgeVerts ) ) mSELDecal->mSize = oldSize; } else if ( mGizmo->getMode() == MoveMode ) mSELDecal->mPosition = gizmoPos; else if ( mGizmo->getMode() == RotateMode ) { mSELDecal->mNormal = upVec; mSELDecal->mTangent = rightVec; } gDecalManager->notifyDecalModified( mSELDecal ); Con::executef( this, "syncNodeDetails" ); } }
void GuiDecalEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) { mPerformedDragCopy = false; if ( !isFirstResponder() ) setFirstResponder(); bool dblClick = ( event.mouseClickCount > 1 ); // Gather selected decal information RayInfo ri; bool hit = getRayInfo( event, &ri ); Point3F start = event.pos; Point3F end = start + event.vec * 3000.0f; // use visible distance here?? DecalInstance *pDecal = gDecalManager->raycast( start, end ); if( mMode.compare("AddDecalMode") != 0 ) { if ( mSELDecal ) { // If our click hit the gizmo we are done. if ( mGizmo->getSelection() != Gizmo::None ) { mGizmo->on3DMouseDown( event ); char returnBuffer[256]; dSprintf(returnBuffer, sizeof(returnBuffer), "%f %f %f %f %f %f %f", mSELDecal->mPosition.x, mSELDecal->mPosition.y, mSELDecal->mPosition.z, mSELDecal->mTangent.x, mSELDecal->mTangent.y, mSELDecal->mTangent.z, mSELDecal->mSize); Con::executef( this, "prepGizmoTransform", Con::getIntArg(mSELDecal->mId), returnBuffer ); return; } } if ( mHLDecal && pDecal == mHLDecal ) { mHLDecal = NULL; selectDecal( pDecal ); if ( isMethod( "onSelectInstance" ) ) { char idBuf[512]; dSprintf(idBuf, 512, "%i", pDecal->mId); Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() ); } return; } else if ( hit && !pDecal) { if ( dblClick ) setMode( String("AddDecalMode"), true ); return; } } else { // If we accidently hit a decal, then bail(probably an accident). If the use hits the decal twice, // then boot them into selection mode and select the decal. if ( mHLDecal && pDecal == mHLDecal ) { if ( dblClick ) { mHLDecal = NULL; selectDecal( pDecal ); if ( isMethod( "onSelectInstance" ) ) { char idBuf[512]; dSprintf(idBuf, 512, "%i", pDecal->mId); Con::executef( this, "onSelectInstance", String(idBuf).c_str(), pDecal->mDataBlock->lookupName.c_str() ); } setMode( String("SelectDecalMode"), true ); } return; } if ( hit && mCurrentDecalData ) // Create a new decal... { U8 flags = PermanentDecal | SaveDecal; DecalInstance *decalInst = gDecalManager->addDecal( ri.point, ri.normal, 0.0f, mCurrentDecalData, 1.0f, -1, flags ); if ( decalInst ) { // Give the decal an id decalInst->mId = gDecalManager->mDecalInstanceVec.size(); gDecalManager->mDecalInstanceVec.push_back(decalInst); selectDecal( decalInst ); // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiMeshRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. DICreateUndoAction *action = new DICreateUndoAction("Create Decal"); action->addDecal( *decalInst ); action->mEditor = this; // Submit it. undoMan->addAction( action ); if ( isMethod( "onCreateInstance" ) ) { char buffer[512]; dSprintf(buffer, 512, "%i", decalInst->mId); Con::executef( this, "onCreateInstance", buffer, decalInst->mDataBlock->lookupName.c_str()); } } return; } } if ( !mSELDecal ) return; }
void GuiRoadEditorCtrl::on3DMouseDown(const Gui3DMouseEvent & event) { if ( !isFirstResponder() ) setFirstResponder(); // Get the clicked terrain position. Point3F tPos; if ( !getTerrainPos( event, tPos ) ) return; mouseLock(); // Find any road / node at the clicked position. // TODO: handle overlapping roads/nodes somehow, cycle through them. DecalRoad *roadPtr = NULL; S32 closestNodeIdx = -1; F32 closestDist = F32_MAX; DecalRoad *closestNodeRoad = NULL; // First, find the closest node in any road to the clicked position. for ( SimSetIterator iter(mRoadSet); *iter; ++iter ) { roadPtr = static_cast<DecalRoad*>( *iter ); U32 idx; if ( roadPtr->getClosestNode( tPos, idx ) ) { Point3F nodePos = roadPtr->getNodePosition(idx); F32 dist = ( nodePos - tPos ).len(); if ( dist < closestDist ) { closestNodeIdx = idx; closestDist = dist; closestNodeRoad = roadPtr; } } } // // Second, determine if the screen-space node rectangle // contains the clicked position. bool nodeClicked = false; S32 clickedNodeIdx = -1; if ( closestNodeIdx != -1 ) { Point3F nodePos = closestNodeRoad->getNodePosition( closestNodeIdx ); Point3F temp; project( nodePos, &temp ); Point2I screenPos( temp.x, temp.y ); RectI nodeRect( screenPos - mNodeHalfSize, mNodeHalfSize * 2 ); nodeClicked = nodeRect.pointInRect( event.mousePoint ); if ( nodeClicked ) clickedNodeIdx = closestNodeIdx; } // // Determine the clickedRoad // DecalRoad *clickedRoadPtr = NULL; U32 insertNodeIdx = 0; if ( nodeClicked && (mSelRoad == NULL || closestNodeRoad == mSelRoad) ) { // If a node was clicked, the owning road is always // considered the clicked road. clickedRoadPtr = closestNodeRoad; } else { // check the selected road first if ( mSelRoad != NULL && mSelRoad->containsPoint( tPos, &insertNodeIdx ) ) { clickedRoadPtr = mSelRoad; nodeClicked = false; clickedNodeIdx = -1; } else { // Otherwise, we must ask each road if it contains // the clicked pos. for ( SimSetIterator iter(mRoadSet); *iter; ++iter ) { roadPtr = static_cast<DecalRoad*>( *iter ); if ( roadPtr->containsPoint( tPos, &insertNodeIdx ) ) { clickedRoadPtr = roadPtr; break; } } } } // shortcuts bool dblClick = ( event.mouseClickCount > 1 ); if( dblClick ) { if( mMode == mSelectRoadMode ) { setMode( mAddRoadMode, true ); return; } if( mMode == mAddNodeMode ) { // Delete the node attached to the cursor. deleteSelectedNode(); mMode = mAddRoadMode; return; } } //this check is here in order to bounce back from deleting a whole road with ctrl+z //this check places the editor back into addroadmode if ( mMode == mAddNodeMode ) { if ( !mSelRoad ) mMode = mAddRoadMode; } if ( mMode == mSelectRoadMode ) { // Did not click on a road or a node. if ( !clickedRoadPtr ) { setSelectedRoad( NULL ); setSelectedNode( -1 ); return; } // Clicked on a road that wasn't the currently selected road. if ( clickedRoadPtr != mSelRoad ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( -1 ); return; } // Clicked on a node in the currently selected road that wasn't // the currently selected node. if ( nodeClicked ) { setSelectedNode( clickedNodeIdx ); return; } // Clicked a position on the currently selected road // that did not contain a node. //U32 newNode = clickedRoadPtr->insertNode( tPos, mDefaultWidth, insertNodeIdx ); //setSelectedNode( newNode ); } else if ( mMode == mAddRoadMode ) { if ( nodeClicked && clickedRoadPtr ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx ); mIsDirty = true; return; } else if ( clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 ) { setSelectedRoad( clickedRoadPtr ); setSelectedNode( clickedNodeIdx ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; mSelNode = mSelRoad->addNode( tPos, mDefaultWidth ); mIsDirty = true; setSelectedNode( mSelNode ); return; } } DecalRoad *newRoad = new DecalRoad; newRoad->mMaterialName = mMaterialName; newRoad->registerObject(); // Add to MissionGroup SimGroup *missionGroup; if ( !Sim::findObject( "MissionGroup", missionGroup ) ) Con::errorf( "GuiDecalRoadEditorCtrl - could not find MissionGroup to add new DecalRoad" ); else missionGroup->addObject( newRoad ); newRoad->insertNode( tPos, mDefaultWidth, 0 ); U32 newNode = newRoad->insertNode( tPos, mDefaultWidth, 1 ); // Always add to the end of the road, the first node is the start. mAddNodeIdx = U32_MAX; setSelectedRoad( newRoad ); setSelectedNode( newNode ); mMode = mAddNodeMode; // Disable the hover node while in addNodeMode, we // don't want some random node enlarged. mHoverNode = -1; // Grab the mission editor undo manager. UndoManager *undoMan = NULL; if ( !Sim::findObject( "EUndoManager", undoMan ) ) { Con::errorf( "GuiRoadEditorCtrl::on3DMouseDown() - EUndoManager not found!" ); return; } // Create the UndoAction. MECreateUndoAction *action = new MECreateUndoAction("Create Road"); action->addObject( newRoad ); // Submit it. undoMan->addAction( action ); //send a callback to script after were done here if one exists if ( isMethod( "onRoadCreation" ) ) Con::executef( this, "onRoadCreation" ); return; } else if ( mMode == mAddNodeMode ) { // Oops the road got deleted, maybe from an undo action? // Back to NormalMode. if ( mSelRoad ) { // A double-click on a node in Normal mode means set AddNode mode. if ( clickedNodeIdx == 0 ) { submitUndo( "Add Node" ); mAddNodeIdx = clickedNodeIdx; mMode = mAddNodeMode; mSelNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx ); mIsDirty = true; setSelectedNode( mSelNode ); return; } else { if( clickedRoadPtr && clickedNodeIdx == clickedRoadPtr->mNodes.size() - 1 ) { submitUndo( "Add Node" ); mAddNodeIdx = U32_MAX; mMode = mAddNodeMode; mSelNode = mSelRoad->addNode( tPos, mDefaultWidth ); mIsDirty = true; setSelectedNode( mSelNode ); return; } else { submitUndo( "Insert Node" ); // A single-click on empty space while in // AddNode mode means insert / add a node. //submitUndo( "Add Node" ); //F32 width = mSelRoad->getNodeWidth( mSelNode ); U32 newNode = mSelRoad->insertNode( tPos, mDefaultWidth, mAddNodeIdx); mIsDirty = true; setSelectedNode( newNode ); return; } } } } else if ( mMode == mInsertPointMode && mSelRoad != NULL) { if ( clickedRoadPtr == mSelRoad ) { F32 w0 = mSelRoad->getNodeWidth( insertNodeIdx ); F32 w1 = mSelRoad->getNodeWidth( insertNodeIdx + 1 ); F32 width = ( w0 + w1 ) * 0.5f; submitUndo( "Insert Node" ); U32 newNode = mSelRoad->insertNode( tPos, width, insertNodeIdx + 1); mIsDirty = true; setSelectedNode( newNode ); return; } } else if ( mMode == mRemovePointMode && mSelRoad != NULL) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); deleteSelectedNode(); return; } } else if ( mMode == mMovePointMode ) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); return; } } else if ( mMode == mScalePointMode ) { if ( nodeClicked && clickedRoadPtr == mSelRoad ) { setSelectedNode( clickedNodeIdx ); return; } } }