diff --git a/addons/gdcef/demos/JS/Control.gd b/addons/gdcef/demos/JS/Control.gd
index 35465f8..72812d8 100644
--- a/addons/gdcef/demos/JS/Control.gd
+++ b/addons/gdcef/demos/JS/Control.gd
@@ -22,14 +22,10 @@ const BROWSER_NAME = "player_stats"
# ==============================================================================
func _ready():
initialize_cef()
-# expose_methods()
pass
-# ==============================================================================
-# Expose methods to JavaScript via CEF
-# ==============================================================================
-#func expose_methods():
-# pass
+func maMethodeGodot(message):
+ print("Message reçu depuis JavaScript : ", message)
# ==============================================================================
# Change character's weapon
@@ -95,12 +91,14 @@ func get_character_state() -> Dictionary:
# ==============================================================================
# CEF Callback when a page has ended to load with success.
+# TODO on page_unload ?
# ==============================================================================
func _on_page_loaded(browser):
print("The browser " + browser.name + " has loaded " + browser.get_url())
- $CEF.register_method(self, browser, "change_weapon")
- $CEF.register_method(self, browser, "set_character_name")
- $CEF.register_method(self, browser, "modify_xp")
+ browser.register_method(Callable(self, "change_weapon"))
+ browser.register_method(Callable(self, "set_character_name"))
+ browser.register_method(Callable(self, "modify_xp"))
+ browser.register_method(Callable(self, "maMethodeGodot"))
pass
# ==============================================================================
@@ -144,7 +142,7 @@ func initialize_cef():
# Load the HTML file containing the JavaScript code
# ==============================================================================
func _load_html_file():
- var file = FileAccess.open("res://character-management-ui.html", FileAccess.READ)
+ var file = FileAccess.open("/home/qq/MyGitHub/gdcef/addons/gdcef/demos/JS/qq.html", FileAccess.READ)
var content = file.get_as_text()
file.close()
return content
diff --git a/addons/gdcef/demos/JS/qq.html b/addons/gdcef/demos/JS/qq.html
new file mode 100644
index 0000000..436de1f
--- /dev/null
+++ b/addons/gdcef/demos/JS/qq.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Character Management UI
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/gdcef/gdcef/src/gdbrowser.cpp b/addons/gdcef/gdcef/src/gdbrowser.cpp
index 9b999ec..76687ac 100644
--- a/addons/gdcef/gdcef/src/gdbrowser.cpp
+++ b/addons/gdcef/gdcef/src/gdbrowser.cpp
@@ -23,8 +23,8 @@
// SOFTWARE.
//*****************************************************************************
-//------------------------------------------------------------------------------
#include "gdbrowser.hpp"
+#include "godot_js_binder.hpp"
#include "helper_config.hpp"
#include "helper_files.hpp"
@@ -153,6 +153,8 @@ void GDBrowserView::_bind_methods()
&GDBrowserView::getAudioStreamer);
ClassDB::bind_method(D_METHOD("get_pixel_color", "x", "y"),
&GDBrowserView::getPixelColor);
+ ClassDB::bind_method(D_METHOD("register_method"),
+ &GDBrowserView::registerGodotMethod);
// Signals
ADD_SIGNAL(MethodInfo("on_download_updated",
@@ -893,53 +895,81 @@ void GDBrowserView::onDownloadUpdated(
}
//------------------------------------------------------------------------------
-bool GDBrowserView::Impl::OnProcessMessageReceived(
+void GDBrowserView::registerGodotMethod(const godot::Callable& callable)
+{
+ godot::String method_name = callable.get_method();
+
+ BROWSER_DEBUG("Registering gdscript method "
+ << method_name.utf8().get_data());
+ if (!callable.is_valid())
+ {
+ BROWSER_ERROR("Invalid callable provided");
+ return;
+ }
+
+ std::string key = method_name.utf8().get_data();
+ m_js_bindings[key] = callable;
+}
+
+//------------------------------------------------------------------------------
+bool GDBrowserView::onProcessMessageReceived(
CefRefPtr browser,
CefRefPtr frame,
CefProcessId source_process,
CefRefPtr message)
{
+ BROWSER_DEBUG("Received message " << message->GetName().ToString());
if (message->GetName() != CALL_GODOT_METHOD)
{
+ BROWSER_DEBUG("Not method " << CALL_GODOT_METHOD);
return false;
}
- CefRefPtr args = message->GetArgumentList();
- if (args->GetSize() < 1)
+ if (message->GetArgumentList()->GetSize() < 1)
{
+ BROWSER_ERROR("Expected method name as first argument");
return false;
}
- // Get method name from first argument
- CefString method_name = args->GetString(0);
+ // Create the callable key
+ std::string key = message->GetArgumentList()->GetString(0).ToString();
+
+ // Does not exist ?
+ auto callable = m_js_bindings[key];
+ if (!callable.is_valid())
+ {
+ BROWSER_ERROR("Callable not found for method " << key);
+ return false;
+ }
- // Convert CEF arguments to Godot arguments
- godot::Array godot_args;
- for (size_t i = 1; i < args->GetSize(); ++i)
+ // Convert the message arguments to a Godot Array
+ godot::Array args;
+ auto message_args = message->GetArgumentList();
+ for (size_t i = 1; i < message_args->GetSize(); ++i)
{
- switch (args->GetType(i))
+ switch (message_args->GetType(i))
{
case VTYPE_BOOL:
- godot_args.push_back(args->GetBool(i));
+ args.push_back(message_args->GetBool(i));
break;
case VTYPE_INT:
- godot_args.push_back(args->GetInt(i));
+ args.push_back(message_args->GetInt(i));
break;
case VTYPE_DOUBLE:
- godot_args.push_back(args->GetDouble(i));
+ args.push_back(message_args->GetDouble(i));
break;
case VTYPE_STRING:
- godot_args.push_back(
- godot::String(args->GetString(i).ToString().c_str()));
+ args.push_back(godot::String(
+ message_args->GetString(i).ToString().c_str()));
break;
default:
// For unsupported types, pass as string
- godot_args.push_back(
- godot::String(args->GetString(i).ToString().c_str()));
+ args.push_back(godot::String(
+ message_args->GetString(i).ToString().c_str()));
}
}
- // Call the Godot method
- m_owner.call_deferred(method_name.ToString().c_str(), godot_args);
+ // Call the function
+ callable.callv(args);
return true;
}
\ No newline at end of file
diff --git a/addons/gdcef/gdcef/src/gdbrowser.hpp b/addons/gdcef/gdcef/src/gdbrowser.hpp
index 3bfbc8d..8f66ec2 100644
--- a/addons/gdcef/gdcef/src/gdbrowser.hpp
+++ b/addons/gdcef/gdcef/src/gdbrowser.hpp
@@ -189,11 +189,18 @@ class GDBrowserView: public godot::Node
return this;
}
+ // ---------------------------------------------------------------------
+ //! \brief Called when a message is received from a different process.
+ // ---------------------------------------------------------------------
virtual bool
OnProcessMessageReceived(CefRefPtr browser,
CefRefPtr frame,
CefProcessId source_process,
- CefRefPtr message) override;
+ CefRefPtr message) override
+ {
+ return m_owner.onProcessMessageReceived(
+ browser, frame, source_process, message);
+ }
private: // CefRenderHandler interfaces
@@ -674,6 +681,11 @@ class GDBrowserView: public godot::Node
// -------------------------------------------------------------------------
godot::Color getPixelColor(int x, int y) const;
+ // -------------------------------------------------------------------------
+ //! \brief Register a Godot method in the JavaScript context
+ // -------------------------------------------------------------------------
+ void registerGodotMethod(const godot::Callable& callable);
+
private:
void resize_(int width, int height);
@@ -775,6 +787,14 @@ class GDBrowserView: public godot::Node
CefRefPtr download_item,
CefRefPtr callback);
+ // -------------------------------------------------------------------------
+ //! \brief Called when a message is received from a different process.
+ // -------------------------------------------------------------------------
+ bool onProcessMessageReceived(CefRefPtr browser,
+ CefRefPtr frame,
+ CefProcessId source_process,
+ CefRefPtr message);
+
private:
//! \brief CEF interface implementation
@@ -824,6 +844,9 @@ class GDBrowserView: public godot::Node
//! \brief Download folder (configured from Browser config)
fs::path m_download_folder;
+
+ //! \brief
+ std::unordered_map m_js_bindings;
};
#if !defined(_WIN32)
diff --git a/addons/gdcef/gdcef/src/gdcef.cpp b/addons/gdcef/gdcef/src/gdcef.cpp
index 1ba1e8d..572cad3 100644
--- a/addons/gdcef/gdcef/src/gdcef.cpp
+++ b/addons/gdcef/gdcef/src/gdcef.cpp
@@ -130,8 +130,6 @@ void GDCef::_bind_methods()
ClassDB::bind_method(D_METHOD("shutdown"), &GDCef::shutdown);
ClassDB::bind_method(D_METHOD("is_alive"), &GDCef::isAlive);
ClassDB::bind_method(D_METHOD("get_error"), &GDCef::getError);
- ClassDB::bind_method(D_METHOD("register_method"),
- &GDCef::registerGodotMethod);
}
//------------------------------------------------------------------------------
@@ -584,61 +582,6 @@ GDBrowserView* GDCef::createBrowser(godot::String const& url,
return browser;
}
-//------------------------------------------------------------------------------
-//! \brief Method to register Godot methods in the JavaScript context
-//! \param [in] godot_object The Godot object containing the method to register
-//! \param [in] method_name The name of the method to register
-//------------------------------------------------------------------------------
-void GDCef::registerGodotMethod(godot::Object* godot_object,
- GDBrowserView* browser,
- godot::String const& method_name)
-{
- if (godot_object == nullptr)
- {
- GDCEF_ERROR("Invalid Godot object passed to registerGodotMethod");
- return;
- }
-
- if (browser == nullptr)
- {
- GDCEF_ERROR("Invalid browser passed to registerGodotMethod");
- return;
- }
-
- // Check that the method exists in the Godot object.
- if (!godot_object->has_method(method_name))
- {
- GDCEF_ERROR("Method " << method_name.utf8().get_data()
- << " does not exist in the Godot object");
- return;
- }
-
- // Handle private GDScript methods (starting with "_").
- // Remove the "_" initial for the JavaScript method name
- godot::String js_method_name = method_name;
- if (method_name.begins_with("_"))
- {
- js_method_name = method_name.substr(1);
- }
-
- // Inject the JavaScript code to create the function
- std::string js_code =
- "window.godot." + std::string(js_method_name.utf8().get_data()) +
- " = function() { return window.godot.callGodotMethod('" +
- std::string(js_method_name.utf8().get_data()) + "', ...arguments); };";
-
- // Get the active browser from the caller
- godot::Node* caller = godot::Object::cast_to(godot_object);
- if (caller == nullptr)
- {
- GDCEF_ERROR("Caller object is not a Node");
- return;
- }
-
- // Find the browser in the caller's children
- browser->executeJavaScript(js_code.c_str());
-}
-
//------------------------------------------------------------------------------
void GDCef::Impl::OnAfterCreated(CefRefPtr /*browser*/)
{
diff --git a/addons/gdcef/gdcef/src/gdcef.hpp b/addons/gdcef/gdcef/src/gdcef.hpp
index 6e3cf6a..a6ec768 100644
--- a/addons/gdcef/gdcef/src/gdcef.hpp
+++ b/addons/gdcef/gdcef/src/gdcef.hpp
@@ -108,13 +108,6 @@ class GDCef: public godot::Node
// -------------------------------------------------------------------------
bool isAlive();
- // -------------------------------------------------------------------------
- //! \brief Register a Godot method in the JavaScript context
- // -------------------------------------------------------------------------
- void registerGodotMethod(godot::Object* godot_object,
- GDBrowserView* browser,
- const godot::String& method_name);
-
// -------------------------------------------------------------------------
//! \brief Return the latest error.
// -------------------------------------------------------------------------
diff --git a/addons/gdcef/gdcef/src/godot_js_binder.cpp b/addons/gdcef/gdcef/src/godot_js_binder.cpp
index 5f7900e..ed8f9ce 100644
--- a/addons/gdcef/gdcef/src/godot_js_binder.cpp
+++ b/addons/gdcef/gdcef/src/godot_js_binder.cpp
@@ -25,9 +25,6 @@
#include "godot_js_binder.hpp"
-static CefRefPtr GodotToV8(const godot::Variant& godot_value);
-static godot::Variant V8ToGodot(CefRefPtr v8_value);
-
//------------------------------------------------------------------------------
bool GodotMethodInvoker::Execute(const CefString& name,
CefRefPtr object,
@@ -51,7 +48,7 @@ bool GodotMethodInvoker::Execute(const CefString& name,
}
//------------------------------------------------------------------------------
-static CefRefPtr GodotToV8(const godot::Variant& godot_value)
+CefRefPtr GodotToV8(const godot::Variant& godot_value)
{
switch (godot_value.get_type())
{
@@ -105,7 +102,7 @@ static CefRefPtr GodotToV8(const godot::Variant& godot_value)
}
//------------------------------------------------------------------------------
-static godot::Variant V8ToGodot(CefRefPtr v8_value)
+godot::Variant V8ToGodot(CefRefPtr v8_value)
{
if (!v8_value.get())
{
diff --git a/addons/gdcef/gdcef/src/godot_js_binder.hpp b/addons/gdcef/gdcef/src/godot_js_binder.hpp
index 5e9ada4..419753b 100644
--- a/addons/gdcef/gdcef/src/godot_js_binder.hpp
+++ b/addons/gdcef/gdcef/src/godot_js_binder.hpp
@@ -34,6 +34,16 @@
// Chromium Embedded Framework
#include "cef_v8.h"
+// -----------------------------------------------------------------------------
+//! \brief Convert a Godot variant to a V8 value
+// -----------------------------------------------------------------------------
+CefRefPtr GodotToV8(const godot::Variant& godot_value);
+
+// -----------------------------------------------------------------------------
+//! \brief Convert a V8 value to a Godot variant
+// -----------------------------------------------------------------------------
+godot::Variant V8ToGodot(CefRefPtr v8_value);
+
// ****************************************************************************
//! \class GodotMethodInvoker
//! \brief Class to handle binding between JavaScript and GDScript methods
diff --git a/addons/gdcef/render_process/src/render_process.cpp b/addons/gdcef/render_process/src/render_process.cpp
index 54a9c3a..f82ef4b 100644
--- a/addons/gdcef/render_process/src/render_process.cpp
+++ b/addons/gdcef/render_process/src/render_process.cpp
@@ -54,9 +54,13 @@ bool GodotMethodHandler::Execute(const CefString& name,
CefRefPtr& retval,
CefString& exception)
{
+ DEBUG_RENDER_PROCESS(name.ToString());
+
// Function does not exist.
if (name != CALL_GODOT_METHOD)
{
+ exception = "Function does not exist";
+ DEBUG_RENDER_PROCESS(exception.ToString());
return false;
}
@@ -64,6 +68,7 @@ bool GodotMethodHandler::Execute(const CefString& name,
if (m_browser == nullptr)
{
exception = "Browser pointer at NULL";
+ DEBUG_RENDER_PROCESS(exception.ToString());
return true;
}
@@ -71,6 +76,7 @@ bool GodotMethodHandler::Execute(const CefString& name,
if (arguments.size() < 1 || !arguments[0]->IsString())
{
exception = "First argument must be the method name";
+ DEBUG_RENDER_PROCESS(exception.ToString());
return false;
}