Making the addon project independent
This commit is contained in:
parent
7f2f9a4e6c
commit
dda5fdc8a5
17 changed files with 181 additions and 75 deletions
|
@ -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
|
|
|
@ -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>
|
||||||
|
|
10
__init__.py
10
__init__.py
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
BIN
addon/icons/godot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
addon/icons/godot_bridge.png
Normal file
BIN
addon/icons/godot_bridge.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.3 KiB |
|
@ -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():
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
32
addon/parameters/__init__.py
Normal file
32
addon/parameters/__init__.py
Normal 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)
|
21
addon/parameters/sidecar.py
Normal file
21
addon/parameters/sidecar.py
Normal 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"}
|
|
@ -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():
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
|
@ -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()
|
Loading…
Reference in a new issue