Jump to content

Plugins in Leadwerks Game Engine 5


Josh

15,006 views

 Share

Internally, Leadwerks Editor uses an EventHandler class for every interface in the program. The material editor is a class extended from the EventHandler. So is the little window that has all the controls to calculate normals. So is every viewport.

The event handler class has one important function:

Event ProcessEvent(Event)

Every EventHandler has access to events as they occur. This is how all program actions are handled in the editor.

The plugin system will work by hooking into the event system. Each plugin will have a Lua script that receive events before the rest of the program sees them:

function Script:ProcessEvent(event)
	return event
end

If the plugin makes no changes to the event then it simply returns the original event. The returned event is then sent to other event handlers.

Here is an example of a plugin that would disable the close window button on the main window. Because the function returns nil the event is discarded before the main window ever evaluates it:

function Script:ProcessEvent(event)
	if event.id == EVENT_WINDOWCLOSE and event.source == editor.mainwindow then
		return nil
	else
		return event
	end
end

Here is an example of a very mean plugin that would make it so that clicking the File > Open menu item in the main window quits the program:

function Script:ProcessEvent(event)
	if event.id == EVENT_MENUEVENT then
		if event.source == editor.mainwindow then
			if event.extra == MENU_FILEOPEN then
				event.id = EVENT_WINDOWCLOSE
			end
		end
	end
  	return event
end

Okay, now let's see if we can design a plugin for something people would actually want. Let's imagine we have a new visual material design system. The exact details of how it works are not important, it's just a system that overrides the default material editor. The design system would require materials to have a special file associated with them with the extension .DESIGN. If you open the material "brick.mat" we will look for a file in the same folder called "brick.design". If the design file is found we open the material in our special editor. If the design file is missing we will just fall back to the default material editor.

Now let's see how our system can handle this:

function Script:Start()
	
	--Create our interface
	self.window = CreateWindow("Material Designer",0,0,800,600,editor.mainwindow,WINDOW_CENTER + WINDOW_TITLEBAR + WINDOW_RESIZABLE)
	
end

function Script:ProcessEvent(event)
	if event.id == EVENT_FILEOPEN

		--Check for material files being opened
		if ExtractExt(event.extra)=="mat"
      
			--Look for design file
			local designfilename = StripExt(event.extra).".design"
			if FileType( designfilename ) == 1 then
				
				--Load the design file
				local stream = ReadFile(designfilename)
				if stream ~= nil then
					
					--Display our custom material editor
					self.window:Show()
					self.window:Activate()

				else
          
					Print("Error: Failed to load design file.")
            
				end
				
				--Discard the event
				return nil
			end
		end
	end
	return event
end

As you can see, this approach is extremely powerful. The event IDs and design rarely change, if ever, so this allows a lot of flexibility and at the same time gives us the optimal compatibility as changes are made to the core editor. With this approach to plugins you can literally do anything you want in the editor.

  • Like 4
  • Thanks 1
  • Upvote 1
 Share

52 Comments


Recommended Comments



1 hour ago, jen said:

Class based approach is difficult to work with. Just look at the UE4 and CryEngine C++ manual, you'll get nowhere. You can always create your own classes.

Classes are fine in any language, it's really just deep hierarchies you want to avoid. The age old composition vs inheritance. Composition can still be done with the idea of classes which basically every programmer knows and is comfortable using in 2018.

Link to comment
13 hours ago, jen said:

"it's really just deep hierarchies you want to avoid"

@Rick Yea that's the problem with the other engines, I found out. The classes in UE4 and CryEngine are too bloated and inaccessible. 

Yes, this is something I’ve always observed. It was a big problem with Torque Engine as well.

Link to comment

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...