//--------------------------------------------------------------------------------------- // Actor@named(Name name) <ThisClass_> static void mthdc_named(SkInvokedMethod * scope_p, SkInstance ** result_pp) { if (result_pp) // Do nothing if result not desired { // Find actor SkClass * sk_class_p; UClass * ue_class_p; SkInstance * instance_p; SkInstance * name_p = scope_p->get_arg(SkArg_1); AActor * actor_p = find_named( name_p->get_class() == SkUEName::get_class() ? name_p->as<SkUEName>() : AStringToFName(name_p->as<SkString>()), scope_p, &sk_class_p, &ue_class_p, &instance_p); #if (SKOOKUM & SK_DEBUG) if (!actor_p) { SK_ERRORX(a_str_format("Tried to get instance named '%s' from class '%s', but no such instance exists!\n", scope_p->get_arg<SkString>(SkArg_1).as_cstr(), ((SkMetaClass *)scope_p->get_topmost_scope())->get_class_info()->get_name().as_cstr_dbg())); } #endif // Create instance from our actor, even if null *result_pp = instance_p ? instance_p : SkUEActor::new_instance(actor_p, ue_class_p, sk_class_p); } }
void SkUEBlueprintInterface::exec_coroutine(FFrame & stack, void * const result_p) { const FunctionEntry & function_entry = static_cast<const FunctionEntry &>(*ms_singleton_p->m_binding_entry_array[stack.CurrentNativeFunction->RepOffset]); SK_ASSERTX(function_entry.m_type == BindingType_Function, "BindingEntry has bad type!"); SK_ASSERTX(function_entry.m_sk_invokable_p->get_invoke_type() == SkInvokable_coroutine, "Must not be coroutine at this point."); // Create invoked coroutine SkInvokedCoroutine * icoroutine_p = SkInvokedCoroutine::pool_new(static_cast<SkCoroutine *>(function_entry.m_sk_invokable_p)); // Get instance of this object SkInstance * this_p = SkUEEntity::new_instance(stack.Object); // Set parameters icoroutine_p->reset(SkCall_interval_always, nullptr, this_p, nullptr, nullptr); #if defined(SKDEBUG_COMMON) // Set with SKDEBUG_ICALL_STORE_GEXPR stored here before calls to argument expressions // overwrite it. const SkExpressionBase * call_expr_p = SkInvokedContextBase::ms_last_expr_p; #endif SKDEBUG_ICALL_SET_EXPR(icoroutine_p, call_expr_p); // Fill invoked coroutine's argument list const SkParamEntry * param_entry_array = function_entry.get_param_entry_array(); icoroutine_p->data_ensure_size(function_entry.m_num_params); for (uint32_t i = 0; i < function_entry.m_num_params; ++i) { const SkParamEntry & param_entry = param_entry_array[i]; icoroutine_p->data_append_arg((*param_entry.m_fetcher_p)(stack)); } // Done with stack - now increment the code ptr unless it is null stack.Code += !!stack.Code; SKDEBUG_HOOK_EXPR(call_expr_p, icoroutine_p, nullptr); #if (SKOOKUM & SK_DEBUG) if (!this_p->get_class()->is_class(*function_entry.m_sk_class_p)) { SK_ERRORX(a_str_format("Attempted to invoke coroutine '%s@%s' via a blueprint of type '%s'. You might have forgotten to specify the SkookumScript type of this blueprint as '%s' in its SkookumScript component.", function_entry.m_sk_class_p->get_name_cstr(), function_entry.m_invokable_name.as_cstr(), this_p->get_class()->get_name_cstr(), function_entry.m_sk_class_p->get_name_cstr())); } else #endif { // Invoke the coroutine on this_p - might return immediately icoroutine_p->on_update(); } // Free if not in use by our invoked coroutine this_p->dereference(); }
void SkUEBlueprintInterface::exec_method(FFrame & stack, void * const result_p, SkInstance * this_p) { const FunctionEntry & function_entry = static_cast<const FunctionEntry &>(*ms_singleton_p->m_binding_entry_array[stack.CurrentNativeFunction->RepOffset]); SK_ASSERTX(function_entry.m_type == BindingType_Function, "BindingEntry has bad type!"); SK_ASSERTX(function_entry.m_sk_invokable_p->get_invoke_type() == SkInvokable_method, "Must not be coroutine or atomic at this point."); SkInvokedMethod imethod(nullptr, this_p, static_cast<SkMethodBase *>(function_entry.m_sk_invokable_p), a_stack_allocate(function_entry.m_sk_invokable_p->get_invoked_data_array_size(), SkInstance*)); SKDEBUG_ICALL_SET_INTERNAL(&imethod); SKDEBUG_HOOK_SCRIPT_ENTRY(function_entry.m_invokable_name); // Fill invoked method's argument list const SkParamEntry * param_entry_array = function_entry.get_param_entry_array(); imethod.data_ensure_size(function_entry.m_num_params); for (uint32_t i = 0; i < function_entry.m_num_params; ++i) { const SkParamEntry & param_entry = param_entry_array[i]; imethod.data_append_arg((*param_entry.m_fetcher_p)(stack)); } // Done with stack - now increment the code ptr unless it is null stack.Code += !!stack.Code; #if (SKOOKUM & SK_DEBUG) if (!this_p->get_class()->is_class(*function_entry.m_sk_class_p)) { SK_ERRORX(a_str_format("Attempted to invoke method '%s@%s' via a blueprint of type '%s'. You might have forgotten to specify the SkookumScript type of this blueprint as '%s' in its SkookumScript component.", function_entry.m_sk_class_p->get_name_cstr(), function_entry.m_invokable_name.as_cstr(), this_p->get_class()->get_name_cstr(), function_entry.m_sk_class_p->get_name_cstr())); } else #endif { // Call method SkInstance * result_instance_p = SkBrain::ms_nil_p; static_cast<SkMethod *>(function_entry.m_sk_invokable_p)->SkMethod::invoke(&imethod, nullptr, &result_instance_p); // We know it's a method so call directly if (function_entry.m_result_getter) { (*function_entry.m_result_getter)(result_p, result_instance_p); } } SKDEBUG_HOOK_SCRIPT_EXIT(); }
int32_t SkUEBlueprintInterface::try_add_binding_entry(UClass * ue_class_p, SkInvokableBase * sk_invokable_p) { // Only look at methods that are annotated as blueprint if (sk_invokable_p->get_annotation_flags() & SkAnnotation_Blueprint) { // If it's a method with no body... if (sk_invokable_p->get_invoke_type() == SkInvokable_method_func || sk_invokable_p->get_invoke_type() == SkInvokable_method_mthd) { // ...it's an event return add_event_entry(ue_class_p, static_cast<SkMethodBase *>(sk_invokable_p)); } else if (sk_invokable_p->get_invoke_type() == SkInvokable_method || sk_invokable_p->get_invoke_type() == SkInvokable_coroutine) { // ...otherwise it's a function/coroutine return add_function_entry(ue_class_p, sk_invokable_p); } else { SK_ERRORX(a_str_format("Trying to export coroutine %s to Blueprints which is atomic. Currently only scripted coroutines can be invoked via Blueprints.", sk_invokable_p->get_name_cstr())); } } return -1; }