Making the addon project independent

This commit is contained in:
Yann Kervran 2024-05-18 13:09:47 +02:00
parent 7f2f9a4e6c
commit dda5fdc8a5
17 changed files with 181 additions and 75 deletions

View file

@ -1,24 +0,0 @@
# This CI is for zipping the plugin when ready for distribution
variables:
ADDON_VERSION: "1.0.0"
stages:
- build
- deploy
build-job:
stage: build
tags:
- Docker
image: alpine
before_script:
- apk add --update zip
script:
- echo "Zipping the plugin in its v$ADDON_VERSION…"
- rm .gitlab-ci.yml
- rm .gitignore
- cd .. && zip -9 -r -q khanat_tools_v1.0.0.zip khanat-tools/*
- mv khanat_tools_v$ADDON_VERSION.zip khanat-tools
artifacts:
paths:
- khanat_tools_v$ADDON_VERSION.zip

View file

@ -1,10 +1,10 @@
# Khanat tools # Godot bridge
## Description ## Description
This Blender addon aims to ease the contribution from Blender for the [Khanat MMORPG project](https://khaganat.net/wikhan/fr:mmorpg). This Blender addon aims to ease the contribution to Godot project for Blender artists.
## Installation ## Installation
Get the zip file and install it in Blender. Get the zip file and install it in Blender as any addon.
## Contributing ## Contributing
If you want to discuss about the plugin, you can join in on XMPP : <xmpp:pirzba@chat.khaganat.net?join> - you can use the web client kindly hosted by Jabberfr : <https://chat.jabberfr.org/converse.js/pirzba@chat.khaganat.net> If you want to discuss about the plugin, you can join in on XMPP : <xmpp:pirzba@chat.khaganat.net?join> - you can use the web client kindly hosted by Jabberfr : <https://chat.jabberfr.org/converse.js/pirzba@chat.khaganat.net>

View file

@ -17,14 +17,14 @@
# END GPL LICENSE BLOCK ##### # END GPL LICENSE BLOCK #####
bl_info = { bl_info = {
"name": "Khanat tools", "name": "Godot bridge",
"author": "Yann Kervran", "author": "Yann Kervran",
"version": (1, 0, 0), "version": (1, 0, 0),
"blender": (3, 4, 0), "blender": (4, 1, 0),
"location": "View3D > UI > N Panel", "location": "View3D > UI > N Panel",
"description": "Toolset for Khanat project", "description": "Toolset for Godot projects",
"doc_url": "https://git.numenaute.org/yannk/khanat-tools", "doc_url": "",
"tracker_url": "https://git.numenaute.org/yannk/khanat-tools/-/issues", "tracker_url": "https://git.numenaute.org/YannK/Godot_bridge/issues",
"category": "Generic" "category": "Generic"
} }

View file

@ -3,7 +3,7 @@ import os
icons_collection = None icons_collection = None
icons_directory = os.path.dirname(__file__) icons_directory = os.path.split(os.path.dirname(__file__))[0] + '/icons'
def get_icon_id(identifier): def get_icon_id(identifier):

BIN
addon/icons/godot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View file

@ -1,7 +1,9 @@
from .panel_main import KH_PT_panel_main from .panel_main import GB_PT_panel_header, GB_PT_panel_parameters, GB_PT_panel_docs
classes = ( classes = (
KH_PT_panel_main, GB_PT_panel_header,
GB_PT_panel_parameters,
GB_PT_panel_docs,
) )
def register_menus(): def register_menus():

View file

@ -4,28 +4,90 @@ from ..operators import readthedocs, export2godot
from ..common import icons from ..common import icons
class KH_PT_panel_main(bpy.types.Panel): class GB_PT_panel_main(bpy.types.Panel):
""" """
Main panel in 3D View Main panel in 3D View
""" """
bl_label = 'Khanat tools'
bl_space_type = 'VIEW_3D' bl_space_type = 'VIEW_3D'
bl_region_type = 'UI' bl_region_type = 'UI'
bl_context = '' bl_context = ''
bl_category = 'Khanat' bl_category = 'Godot bridge'
def draw_header(self, context): def draw_header(self, context):
layout = self.layout layout = self.layout
layout.label(icon_value=icons.get_icon_id("khanat")) layout.label(icon_value=icons.get_icon_id("godot_bridge"))
class GB_PT_panel_header(GB_PT_panel_main):
"""
Header of the panel
"""
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_context = ''
bl_category = 'Godot bridge'
bl_label = 'Godot bridge'
def draw_header(self, context):
layout = self.layout
layout.label(icon_value=icons.get_icon_id("godot"))
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
row = layout.row() row = layout.row()
row.operator(export2godot.KH_OT_export2godot.bl_idname) row.operator(export2godot.GB_OT_export2godot.bl_idname, icon_value=icons.get_icon_id("godot"))
layout.separator() layout.separator()
row = layout.row() class GB_PT_panel_parameters(GB_PT_panel_main):
row.operator(readthedocs.KH_OT_readthedocs.bl_idname, icon_value=72) """
Sub panel for parameters
"""
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_context = ''
bl_category = 'Godot bridge'
bl_parent_id = "GB_PT_panel_header"
bl_label = 'Parameters'
def draw_header(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
layout.separator()
row = layout.row()
row.prop(bpy.context.scene, "godot_project_path")
row = layout.row()
row.prop(bpy.context.scene, "blender_repository_path")
row = layout.row()
row.prop(bpy.context.scene, "root_collection")
row = layout.row()
row.prop(bpy.context.scene, "licence")
row = layout.row()
row.prop(bpy.context.scene, "contributor")
class GB_PT_panel_docs(GB_PT_panel_main):
"""
Sub panel for documentation & links
"""
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_context = ''
bl_category = 'Godot bridge'
bl_label = 'Documentation'
bl_parent_id = "GB_PT_panel_header"
def draw_header(self, context):
layout = self.layout
def draw(self, context):
layout = self.layout
row = layout.row()
row.operator(readthedocs.GB_OT_readthedocs.bl_idname, icon_value=72)
layout.separator() layout.separator()

View file

@ -1,9 +1,10 @@
from .readthedocs import KH_OT_readthedocs import bpy
from .export2godot import KH_OT_export2godot from .readthedocs import GB_OT_readthedocs
from .export2godot import GB_OT_export2godot
classes = ( classes = (
KH_OT_readthedocs, GB_OT_readthedocs,
KH_OT_export2godot GB_OT_export2godot,
) )

View file

@ -5,9 +5,9 @@ import re
from ..common import addon from ..common import addon
from ..common import validate_name from ..common import validate_name
class KH_OT_export2godot(bpy.types.Operator): class GB_OT_export2godot(bpy.types.Operator):
"""Export whole collections to Godot throught glTF format""" """Export whole collections to Godot throught glTF format"""
bl_idname = "kh.export2godot" bl_idname = "gb.export2godot"
bl_label = "Export to Godot project" bl_label = "Export to Godot project"
bl_options = {'REGISTER', 'UNDO'} bl_options = {'REGISTER', 'UNDO'}
@ -15,11 +15,16 @@ class KH_OT_export2godot(bpy.types.Operator):
return self.execute(context) return self.execute(context)
def execute(self, context): def execute(self, context):
prefs = addon.get_prefs() # prefs = addon.get_prefs()
print("Root collection : {}".format(prefs.root_collection)) # print("Root collection : {}".format(prefs.default_root_collection))
print("Godot path : {}".format(prefs.godot_project_path)) # print("Godot path : {}".format(prefs.default_godot_project_path))
# print("Blender repository path : {}".format(
# prefs.default_blender_repository_path))
print("Root collection : {}".format(context.scene.root_collection))
print("Godot path : {}".format(context.scene.godot_project_path))
print("Blender repository path : {}".format( print("Blender repository path : {}".format(
prefs.blender_repository_path)) context.scene.blender_repository_path))
def save_file_beforehand(): def save_file_beforehand():
self.report( self.report(
@ -34,7 +39,7 @@ class KH_OT_export2godot(bpy.types.Operator):
""" """
final_path = bpy.data.filepath.replace( final_path = bpy.data.filepath.replace(
prefs.blender_repository_path, prefs.godot_project_path) context.scene.blender_repository_path, context.scene.godot_project_path)
gltf_path = os.path.splitext(final_path)[0] gltf_path = os.path.splitext(final_path)[0]
if not os.path.isdir(gltf_path): if not os.path.isdir(gltf_path):
os.makedirs(gltf_path) os.makedirs(gltf_path)
@ -70,12 +75,13 @@ class KH_OT_export2godot(bpy.types.Operator):
filepath="{}/{}".format(gltf_path, filename), filepath="{}/{}".format(gltf_path, filename),
export_format="GLTF_SEPARATE", # Export glTF Separate (.gltf + .bin + textures), Exports multiple files, with separate JSON, binary and texture data export_format="GLTF_SEPARATE", # Export glTF Separate (.gltf + .bin + textures), Exports multiple files, with separate JSON, binary and texture data
export_texture_dir="{}_{}_textures".format((os.path.splitext(os.path.basename(gltf_path)))[0], filename), # Textures folder export_texture_dir="{}_{}_textures".format((os.path.splitext(os.path.basename(gltf_path)))[0], filename), # Textures folder
export_copyright=prefs.licence, export_copyright=context.scene.licence,
use_active_collection = True, use_active_collection = True,
use_renderable = True, use_renderable = True,
export_cameras=False, export_cameras=False,
export_lights=False, export_lights=False,
export_apply=True # Applique les modifiers export_apply=True, # Apply modifiers
export_gn_mesh=True # Apply Geometry Nodes Instance
) )
tscn_collections = [ coll for coll in bpy.data.collections if scene_collection.user_of_id(coll)] tscn_collections = [ coll for coll in bpy.data.collections if scene_collection.user_of_id(coll)]
@ -100,10 +106,10 @@ class KH_OT_export2godot(bpy.types.Operator):
save_file_beforehand() save_file_beforehand()
else: else:
try: try:
scn_col = bpy.data.collections[prefs.root_collection] scn_col = bpy.data.collections[context.scene.root_collection]
except KeyError: except KeyError:
self.report({"WARNING"}, self.report({"WARNING"},
"No \"{}\" root collection in the file - skipping export".format(prefs.root_collection)) "No \"{}\" root collection in the file - skipping export".format(context.scene.root_collection))
return {"CANCELLED"} return {"CANCELLED"}
# Create the proper destination path # Create the proper destination path

View file

@ -1,17 +1,17 @@
import bpy import bpy
class KH_OT_readthedocs(bpy.types.Operator): class GB_OT_readthedocs(bpy.types.Operator):
"""Check online documentation for development""" """Check online documentation about the addon"""
bl_idname="kh.readthedocs" bl_idname="gb.readthedocs"
bl_label="Online documentation" bl_label="Online documentation"
bl_description="Go to Khanat Development Guide" bl_description="Go to Godot bridge documentation"
bl_options= {"REGISTER", "UNDO"} bl_options= {"REGISTER", "UNDO"}
def invoke (self, context, event): def invoke (self, context, event):
return self.execute(context) return self.execute(context)
def execute(self, context): def execute(self, context):
bpy.ops.wm.url_open("INVOKE_DEFAULT", url="https://git.numenaute.org/khaganat/mmorpg_khanat/khanat_gamedev_guide") bpy.ops.wm.url_open("INVOKE_DEFAULT", url="https://git.numenaute.org/YannK/Godot_bridge_docs")
return {"FINISHED"} return {"FINISHED"}

View file

@ -0,0 +1,32 @@
import bpy
from ..common import addon
from .sidecar import GB_sidecar
prefs = addon.get_prefs()
PARAMS = [
('godot_project_path', bpy.props.StringProperty(name="Godot project path", subtype='DIR_PATH', default=prefs.default_godot_project_path )),
('blender_repository_path', bpy.props.StringProperty(name="Blender repository root", subtype='DIR_PATH', default=prefs.default_blender_repository_path)),
('root_collection', bpy.props.StringProperty(name="Root collection", default=prefs.default_root_collection)),
('licence', bpy.props.StringProperty(name="Licence", default=prefs.default_licence)),
('contributor', bpy.props.StringProperty(name="Contributor", default=prefs.default_contributor)),
]
classes = (
GB_sidecar,
)
def register_parameters():
for (param_name, param_value) in PARAMS:
setattr(bpy.types.Scene, param_name, param_value)
from bpy.utils import register_class
for cls in classes:
register_class(cls)
def unregister_parameters():
for (param_name, _) in PARAMS:
delattr(bpy.types.Scene, param_name)
from bpy.utils import unregister_class
for cls in classes:
unregister_class(cls)

View file

@ -0,0 +1,21 @@
import os
import bpy
class GB_sidecar(bpy.types.Operator):
"""
Handling of sidecar file
"""
bl_idname = "gb.sidecar"
bl_label = "Sidecar file handling for Godot bridge"
bl_options = {'REGISTER', 'UNDO'}
def invoke(self, context, event):
return self.execute(context)
def execute(self, context):
return {"FINISHED"}
def read(filename):
print("filename: {}".format(filename))
return {"FINISHED"}

View file

@ -1,9 +1,9 @@
import bpy import bpy
from .preferences import KH_Prefs from .preferences import GB_Prefs
classes = ( classes = (
KH_Prefs, GB_Prefs,
) )
def register_preferences(): def register_preferences():

View file

@ -5,34 +5,34 @@ from bpy.props import StringProperty, IntProperty, BoolProperty
from ..common import addon from ..common import addon
class KH_Prefs(bpy.types.AddonPreferences): class GB_Prefs(bpy.types.AddonPreferences):
bl_idname = addon.addon_name bl_idname = addon.addon_name
# TODO EnumProperty to get list of projects to choose from # TODO EnumProperty to get list of projects to choose from
godot_project_path: StringProperty( default_godot_project_path: StringProperty(
name="Godot project path", name="Godot project path",
subtype='DIR_PATH', subtype='DIR_PATH',
default="//godot_project/" default="//godot_project/"
) )
blender_repository_path: StringProperty( default_blender_repository_path: StringProperty(
name="Blender repository root", name="Blender repository root",
subtype='DIR_PATH', subtype='DIR_PATH',
default="//" default="//"
) )
root_collection: StringProperty( default_root_collection: StringProperty(
name="Root collection", name="Root collection",
default="khanat", default="khanat",
) )
licence: StringProperty( default_licence: StringProperty(
name="Licence", name="Licence",
default="CC BY SA Khaganat", default="CC BY SA Khaganat",
) )
contributor: StringProperty( default_contributor: StringProperty(
name="Contributor", name="Contributor",
default="", default="",
) )
@ -40,11 +40,11 @@ class KH_Prefs(bpy.types.AddonPreferences):
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
box = layout.box() box = layout.box()
box.prop(self, "godot_project_path") box.prop(self, "default_godot_project_path")
box.prop(self, "blender_repository_path") box.prop(self, "default_blender_repository_path")
box.prop(self, "root_collection") box.prop(self, "default_root_collection")
layout.split() layout.split()
box = layout.box() box = layout.box()
box.prop(self, "licence") box.prop(self, "default_licence")
box.prop(self, "contributor") box.prop(self, "default_contributor")

View file

@ -6,6 +6,9 @@ def register_addon():
from ..preferences import register_preferences from ..preferences import register_preferences
register_preferences() register_preferences()
from ..parameters import register_parameters
register_parameters()
from ..operators import register_operators from ..operators import register_operators
register_operators() register_operators()
@ -27,5 +30,8 @@ def unregister_addon():
from ..operators import unregister_operators from ..operators import unregister_operators
unregister_operators() unregister_operators()
from ..parameters import unregister_parameters
unregister_parameters()
from ..preferences import unregister_preferences from ..preferences import unregister_preferences
unregister_preferences() unregister_preferences()