void SkUEDelegate::Instance::invoke_as_method(SkObjectBase * scope_p, SkInvokedBase * caller_p, SkInstance ** result_pp, const SkClosureInvokeInfo & invoke_info, const SkExpressionBase * invoking_expr_p) const { uint32_t invoked_data_array_size = invoke_info.m_params_p->get_arg_count_total(); SkInvokedMethod imethod(caller_p, const_cast<Instance *>(this), invoked_data_array_size, a_stack_allocate(invoked_data_array_size, SkInstance*)); // Store expression debug info for next invoked method/coroutine. SKDEBUG_ICALL_STORE_GEXPR(invoking_expr_p); // Must be called before calling argument expressions SKDEBUG_ICALL_SET_EXPR(&imethod, invoking_expr_p); // Append argument list imethod.data_append_args_exprs(invoke_info.m_arguments, *invoke_info.m_params_p, scope_p); // Hook must be called after argument expressions and before invoke() SKDEBUG_HOOK_EXPR(invoking_expr_p, scope_p, &imethod, nullptr, SkDebug::HookContext_peek); // Invoke the UE4 function SkUEReflectionManager::get()->invoke_k2_delegate(as<SkUEDelegate>(), invoke_info.m_params_p, &imethod, result_pp); /* $Revisit - MBreyer Enable this when we support return arguments // Bind any return arguments if (!invoke_info.m_return_args.is_empty()) { imethod.data_bind_return_args(invoke_info.m_return_args, *invoke_info.m_params_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(); }