TEST_F( TestCommandFixture, creatMacro ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { // TODO: wait on controller controller.getValue( counter ); } { auto & commandSystemProvider = getCommandSystemProvider(); auto & history = commandSystemProvider.getHistory(); commandSystemProvider.createMacro( history ); CHECK(commandSystemProvider.getMacros().empty() == false ); } }
//============================================================================== std::string RPURU::resolveContextObjectPropertyPath(const ObjectHandle& contextObject, const char* propertyPath, IDefinitionManager& definitionManager) { assert(contextObject != nullptr); const auto classDef = contextObject.getDefinition(definitionManager); assert(classDef != nullptr); std::string tmp = propertyPath; std::vector<std::string> paths; paths.push_back(tmp); char* pch; pch = strtok(const_cast<char*>(tmp.c_str()), "."); if (pch != NULL) { pch = strtok(NULL, "."); while (pch != NULL) { paths.push_back(pch); pch = strtok(NULL, "."); } } PropertyAccessor pa; for (auto& path : paths) { resolveProperty(contextObject, *classDef, path.c_str(), pa, definitionManager); if (pa.isValid()) { break; } } return pa.getFullPath(); }
//============================================================================== ObjectHandle SetReflectedPropertyCommand::execute( const ObjectHandle & arguments ) const { ReflectedPropertyCommandArgument * commandArgs = arguments.getBase< ReflectedPropertyCommandArgument >(); auto objManager = definitionManager_.getObjectManager(); assert( objManager != nullptr ); ObjectHandle object = objManager->getObject( commandArgs->getContextId() ); if (!object.isValid()) { return CommandErrorCode::INVALID_ARGUMENTS; } PropertyAccessor property = object.getDefinition( definitionManager_ )->bindProperty( commandArgs->getPropertyPath(), object ); if (property.isValid() == false) { //Can't set return CommandErrorCode::INVALID_ARGUMENTS; } const Variant & data = commandArgs->getPropertyValue(); bool br = property.setValue( data ); if (!br) { return CommandErrorCode::INVALID_VALUE; } // Do not return the object // CommandInstance will hold a reference to the return value // and the CommandInstance is stored in the undo/redo history forever // This is due to a circular reference in CommandManagerImpl::pushFrame return nullptr; }
bool BaseGenericObject::setProperty(const char* name, const Variant& value, bool enableNotification) { // Get existing property const IClassDefinition& definition = *this->getDefinition(); ObjectHandle provider = this->getDerivedType(); PropertyAccessor accessor = definition.bindProperty(name, provider); // do nothing if property does not exist and the value is void if (!accessor.isValid() && value.isVoid()) { return false; } // set value to the property if property exists and the value is not void if (accessor.isValid() && !value.isVoid()) { if (enableNotification) { return accessor.setValue(value); } else { return accessor.setValueWithoutNotification(value); } } // Property does not exist // Add new property and set it auto definitionModifier = definition.getDetails().getDefinitionModifier(); if (definitionModifier == nullptr) { return false; } if (accessor.isValid() && value.isVoid()) { definitionModifier->removeProperty(name); return false; } return addProperty(name, value, nullptr, enableNotification); }
Variant BaseGenericObject::invokeProperty(const char* name, const ReflectedMethodParameters& parameters) { const IClassDefinition& definition = *this->getDefinition(); ObjectHandle provider = this->getDerivedType(); PropertyAccessor accessor = definition.bindProperty(name, provider); if (!accessor.isValid()) { TF_ASSERT(false && "Property could not be found"); return Variant(); } return accessor.invoke(parameters); }
//============================================================================== void RPURU::resolveProperty(const ObjectHandle& handle, const IClassDefinition& classDef, const char* propertyPath, PropertyAccessor& o_Pa, IDefinitionManager& definitionManager) { o_Pa = handle.getDefinition(definitionManager)->bindProperty(propertyPath, handle); if (o_Pa.isValid()) { return; } const PropertyIteratorRange& props = classDef.allProperties(); for (PropertyIterator pi = props.begin(); pi != props.end(); ++pi) { std::string parentPath = pi->getName(); const PropertyAccessor& prop = classDef.bindProperty(parentPath.c_str(), handle); assert(prop.isValid()); if (prop.getProperty()->isMethod()) { continue; } const Variant& value = prop.getValue(); if (value.typeIs<ObjectHandle>()) { ObjectHandle subHandle; bool isOk = value.tryCast(subHandle); assert(isOk); if ((subHandle == nullptr) || (subHandle.getDefinition(definitionManager) == nullptr)) { continue; } parentPath = parentPath + "." + propertyPath; resolveProperty(subHandle, *subHandle.getDefinition(definitionManager), parentPath.c_str(), o_Pa, definitionManager); if (o_Pa.isValid()) { return; } } } }
TEST_F( TestCommandFixture, undo_redo ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); int oldValue = -1; { Variant variant = counter.getValue(); CHECK(variant.tryCast( oldValue )); } auto & commandSystemProvider = getCommandSystemProvider(); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } { commandSystemProvider.undo(); CHECK(!commandSystemProvider.canUndo()); CHECK(commandSystemProvider.canRedo()); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(oldValue, value); } { commandSystemProvider.redo(); CHECK(commandSystemProvider.canUndo()); CHECK(!commandSystemProvider.canRedo()); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } }
//============================================================================== bool SetReflectedPropertyCommand::validateArguments(const ObjectHandle& arguments) const { if ( !arguments.isValid() ) { return false; } auto commandArgs = arguments.getBase< ReflectedPropertyCommandArgument >(); if ( commandArgs == nullptr ) { return false; } auto objManager = definitionManager_.getObjectManager(); if ( objManager == nullptr ) { return false; } const ObjectHandle & object = objManager->getObject( commandArgs->getContextId() ); if (!object.isValid()) { return false; } const IClassDefinition* defn = object.getDefinition( definitionManager_ ); PropertyAccessor property = defn->bindProperty(commandArgs->getPropertyPath(), object ); if (property.isValid() == false) { return false; } const MetaType * dataType = commandArgs->getPropertyValue().type(); const MetaType * propertyValueType = property.getValue().type(); if ( !dataType->canConvertTo(propertyValueType) ) { return false; } return true; }
TEST_F( TestCommandFixture, executeMacro ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { // TODO: wait on controller controller.getValue( counter ); } { auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.undo(); auto & history = commandSystemProvider.getHistory(); commandSystemProvider.createMacro( history, "Macro1" ); CHECK(commandSystemProvider.getMacros().empty() == false ); auto macroObj = static_cast<CompoundCommand*>( commandSystemProvider.findCommand( "Macro1" ) )->getMacroObject(); auto instObj = macroObj.getBase<MacroObject>()->executeMacro(); CommandInstancePtr inst = instObj.getBase<CommandInstance>(); commandSystemProvider.waitForInstance( inst ); { PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } } }
TEST_F( TestCommandFixture, runSingleCommand ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); const int TEST_VALUE = 57; { int value = TEST_VALUE; controller.setValue( counter, value ); } { int value = 0; Variant variant = controller.getValue( counter ); CHECK(variant.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); } }
TEST_F( TestCommandFixture, runBatchCommand ) { auto & controller = getReflectionController(); auto objHandle = klass_->createManagedObject(); const int TEST_VALUE = 57; const char * TEST_TEXT = "HelloCommand"; PropertyAccessor counter = klass_->bindProperty("counter", objHandle ); CHECK(counter.isValid()); PropertyAccessor text = klass_->bindProperty( "text", objHandle ); CHECK(text.isValid()); PropertyAccessor incrementCounter = klass_->bindProperty("incrementCounter", objHandle ); CHECK(incrementCounter.isValid()); { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( TEST_VALUE != value ); std::string text_value; Variant variantText = controller.getValue( text ); CHECK( variantText.tryCast( text_value ) ); CHECK( TEST_TEXT != text_value ); } { int value = TEST_VALUE; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, value ); std::string text_value = TEST_TEXT; controller.setValue( text, text_value ); commandSystemProvider.abortBatchCommand(); } { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK(TEST_VALUE != value); std::string text_value; Variant variantText = controller.getValue( text ); CHECK(variantText.tryCast( text_value )); CHECK(TEST_TEXT != text_value); } { int value = TEST_VALUE; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, value ); std::string text_value = TEST_TEXT; controller.setValue( text, text_value ); commandSystemProvider.endBatchCommand(); } { int value = 0; Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(TEST_VALUE, value); std::string text_value; Variant variantText = controller.getValue( text ); CHECK(variantText.tryCast( text_value )); CHECK_EQUAL(TEST_TEXT, text_value); } { Variant variantValue; int value = 0; auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 0 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 1 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 2 ); commandSystemProvider.beginBatchCommand(); controller.setValue( counter, 3 ); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 3 ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 2 ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 1); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 0); commandSystemProvider.endBatchCommand(); variantValue = controller.getValue( counter ); CHECK( variantValue.tryCast( value ) ); CHECK( value == 0); } { int value = 0; controller.setValue( counter, value ); Variant variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(0, value); auto & commandSystemProvider = getCommandSystemProvider(); commandSystemProvider.beginBatchCommand(); controller.invoke( incrementCounter, ReflectedMethodParameters() ); controller.invoke( incrementCounter, ReflectedMethodParameters() ); commandSystemProvider.endBatchCommand(); variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(2, value); commandSystemProvider.beginBatchCommand(); controller.invoke( incrementCounter, ReflectedMethodParameters() ); controller.invoke( incrementCounter, ReflectedMethodParameters() ); commandSystemProvider.abortBatchCommand(); variantValue = controller.getValue( counter ); CHECK(variantValue.tryCast( value )); CHECK_EQUAL(2, value); } }