Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] major material rework #100

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
19931fa
introduced prelit changes
Tarcontar Feb 8, 2020
fab239b
added some prints
Tarcontar Feb 8, 2020
d5e8166
refactor material tests
Michaelschnabel-DM Feb 10, 2020
fc88b24
refactor vertex material creation
Michaelschnabel-DM Feb 10, 2020
87364c8
refactor material creation
Michaelschnabel-DM Feb 10, 2020
cbee5ea
material creation refactoring
Michaelschnabel-DM Feb 11, 2020
87aeec1
added some shader material stuff
Michaelschnabel-DM Feb 12, 2020
7077c67
initial work on better shader setup
Tarcontar Feb 12, 2020
c26097b
added normal map texture
Tarcontar Feb 12, 2020
fbc426e
added specular texture
Tarcontar Feb 12, 2020
6763fea
added emission color, hide unsupported shader inputs
Michaelschnabel-DM Feb 13, 2020
9ed235d
node group creation
Michaelschnabel-DM Feb 13, 2020
24088c3
some work on node group creation
Michaelschnabel-DM Feb 17, 2020
4fe8b3d
material node group creation
Tarcontar Feb 17, 2020
fa0b24b
set material pass index
Tarcontar Feb 17, 2020
578c6d4
link node group instead of principled bsdf
Tarcontar Feb 17, 2020
f9a481f
annotation
Michaelschnabel-DM Feb 18, 2020
da624a4
create alpha pipeline
Tarcontar Feb 18, 2020
7d64364
fixed vertex material creation
Tarcontar Feb 18, 2020
4a3ad0c
small changes
Tarcontar Feb 18, 2020
8a89db7
some work on material pass creation
Michaelschnabel-DM Feb 19, 2020
00d2508
got basic vertex materials working again
Michaelschnabel-DM Feb 20, 2020
2685ed5
got basic shader materials working again
Michaelschnabel-DM Feb 20, 2020
10e3d0a
small changes
Michaelschnabel-DM Feb 20, 2020
08ca04a
got vertex material and normalMapped shader material import working a…
Tarcontar Apr 3, 2020
bbe7634
some more work on various fx shaders
Tarcontar Apr 3, 2020
9551948
got the alpha pipeline working
Tarcontar Apr 4, 2020
367613d
got normalMapped.fx template working
Tarcontar Apr 4, 2020
4e2174a
create normal_mapped completely from xml template
Tarcontar Apr 4, 2020
fda53a8
got objectsGDI working with parenting, added muzzleflash.fx
Tarcontar Apr 4, 2020
a452f59
small fixes
Tarcontar Apr 4, 2020
36552ae
added more shader templates
Tarcontar Apr 4, 2020
827097e
added infantry and basicw3d fx shaders
Tarcontar Apr 5, 2020
28bb6ee
code refactoring and support preset values
Tarcontar Apr 5, 2020
9f6d8aa
more work on material stuff
Tarcontar Apr 6, 2020
7b2c825
some more work on material export rework
Tarcontar Apr 7, 2020
2151f92
more work on vertex material export
Tarcontar Apr 8, 2020
ef83a9d
continued work on material export
Tarcontar Apr 8, 2020
7adc8ca
got shader material roundtrip somewhat working again, first work on v…
Tarcontar Apr 9, 2020
526c44f
more work on material stuff
Tarcontar Apr 11, 2020
aa47ae3
fixed some tests
Tarcontar Apr 11, 2020
f5ec013
some small changes
Tarcontar Apr 12, 2020
7f165bc
some small changes
Tarcontar Apr 12, 2020
794b448
create custom node socket types
Tarcontar Apr 13, 2020
0b22f4f
some changes to material import
Tarcontar Apr 15, 2020
611f1d3
got custom node sockets somewhat working
Tarcontar Apr 16, 2020
7a5b48b
further improved custom node sockets
Tarcontar Apr 16, 2020
30483ff
added surface type dict
Tarcontar Apr 16, 2020
24f0f16
added custom decision node
Tarcontar Apr 17, 2020
6cb9060
fixed face map creation, moved custom properties from object to mesh
Tarcontar Apr 18, 2020
baa9e2c
apply not only x scale on export
Tarcontar Apr 18, 2020
4517ecf
set triangle surface type depending on corresponding face map
Tarcontar Apr 18, 2020
ed1db10
material import rework wip
Tarcontar Apr 19, 2020
cb18c3e
trying to create the pipelines
Tarcontar Apr 19, 2020
fe12c79
lots of improvements on pipeline import and creation
Tarcontar Apr 19, 2020
b0d05a9
added custom sockets for shader enums
Tarcontar Apr 20, 2020
5d192cc
work on unique pipeline import, prelit stuff
Tarcontar Apr 23, 2020
5b41e6b
fixed vertex_material_group
Tarcontar Apr 23, 2020
3dc94e2
small changes
Tarcontar Apr 24, 2020
de8f0b5
this whole node stuff is still crap...
Tarcontar Apr 24, 2020
4f0a175
got custom node sockets working!!!
Tarcontar Jun 29, 2020
181c9e5
working example for default_value
Tarcontar Jun 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/OpenSAGE.BlenderPlugin.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

213 changes: 70 additions & 143 deletions io_mesh_w3d/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# <pep8 compliant>
# Written by Stephan Vedder and Michael Schnabel

import os
import bpy
from bpy.types import Panel
from bpy_extras.io_utils import ImportHelper, ExportHelper
from io_mesh_w3d.export_utils import save
from io_mesh_w3d.custom_properties import *


bl_info = {
'name': 'Import/Export Westwood W3D Format (.w3d/.w3x)',
'author': 'OpenSage Developers',
Expand Down Expand Up @@ -223,21 +227,22 @@ def menu_func_import(self, _context):
self.layout.operator(ImportW3D.bl_idname, text='Westwood W3D (.w3d/.w3x)')


class OBJECT_PROPERTIES_PANEL_PT_w3d(Panel):
class MESH_PROPERTIES_PANEL_PT_w3d(Panel):
bl_label = 'W3D Properties'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'object'
bl_context = 'data'

def draw(self, context):
layout = self.layout
col = layout.column()
col.prop(context.active_object, 'object_type')
if context.active_object.object_type == 'DAZZLE':
mesh = context.active_object.data
col.prop(mesh, 'object_type')
if mesh.object_type == 'DAZZLE':
col = layout.column()
col.prop(context.active_object, 'dazzle_type')
col.prop(mesh, 'dazzle_type')
col = layout.column()
col.prop(context.active_object, 'userText')
col.prop(mesh, 'userText')


class BONE_PROPERTIES_PANEL_PT_w3d(Panel):
Expand All @@ -253,166 +258,88 @@ def draw(self, context):
col.prop(context.active_bone, 'visibility')


class MATERIAL_PROPERTIES_PANEL_PT_w3d(Panel):
bl_label = 'W3D Properties'
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = 'material'
from io_mesh_w3d.common.shading.node_socket_texture import NodeSocketTexture, NodeSocketInterfaceTexture
from io_mesh_w3d.common.shading.node_socket_texture_alpha import NodeSocketTextureAlpha
from io_mesh_w3d.common.shading.node_socket_vec2 import NodeSocketVector2
from io_mesh_w3d.common.shading.node_socket_vec4 import NodeSocketVector4
from io_mesh_w3d.common.shading.node_socket_enum import *

def draw(self, context):
layout = self.layout
mat = context.object.active_material
col = layout.column()
col.prop(mat, 'material_type')

if mat.material_type == 'PRELIT_MATERIAL':
col = layout.column()
col.prop(mat, 'prelit_type')
CLASSES = (
NodeSocketTexture,
NodeSocketInterfaceTexture,
NodeSocketEnum,
NodeSocketEnumMaterialAttributes,
NodeSocketEnumDepthCompare,
NodeSocketEnumDepthMaskWrite,
NodeSocketEnumAlphatest,
NodeSocketEnumDestBlendFunc,
NodeSocketEnumPriGradient,
NodeSocketEnumSecGradient,
NodeSocketEnumSrcBlendFunc,
NodeSocketEnumTexturing,
NodeSocketEnumDetailColorFunc,
NodeSocketEnumDetailAlphaFunc,
NodeSocketTextureAlpha,
NodeSocketVector2,
NodeSocketVector4,
ExportW3D,
ImportW3D,
MESH_PROPERTIES_PANEL_PT_w3d,
BONE_PROPERTIES_PANEL_PT_w3d)

col = layout.column()
col.prop(mat, 'surface_type')
col = layout.column()
col.prop(mat, 'blend_mode')
col = layout.column()
col.prop(mat, 'ambient')
col = layout.column()
col.prop(mat, 'opacity')

if mat.material_type == 'VERTEX_MATERIAL' or mat.material_type == 'PRELIT_MATERIAL':
col = layout.column()
col.prop(mat, 'attributes')
col = layout.column()
col.prop(mat, 'translucency')
col = layout.column()
col.prop(mat, 'vm_args_0')
col = layout.column()
col.prop(mat, 'vm_args_1')
from io_mesh_w3d.common.utils.node_group_creator import NodeGroupCreator
from io_mesh_w3d.common.shading.vertex_material_group import VertexMaterialGroup

col = layout.column()
layout.label(text="Shader Properties")
col = layout.column()
col.prop(mat.shader, 'depth_compare')
col = layout.column()
col.prop(mat.shader, 'depth_mask')
col = layout.column()
col.prop(mat.shader, 'color_mask')
col = layout.column()
col.prop(mat.shader, 'dest_blend')
col = layout.column()
col.prop(mat.shader, 'fog_func')
col = layout.column()
col.prop(mat.shader, 'pri_gradient')
col = layout.column()
col.prop(mat.shader, 'sec_gradient')
col = layout.column()
col.prop(mat.shader, 'src_blend')
col = layout.column()
col.prop(mat.shader, 'texturing')
col = layout.column()
col.prop(mat.shader, 'detail_color_func')
col = layout.column()
col.prop(mat.shader, 'detail_alpha_func')
col = layout.column()
col.prop(mat.shader, 'shader_preset')
col = layout.column()
col.prop(mat.shader, 'alpha_test')
col = layout.column()
col.prop(mat.shader,
'post_detail_color_func')
col = layout.column()
col.prop(mat.shader,
'post_detail_alpha_func')

else:
col = layout.column()
col.prop(mat, 'technique')
col.prop(mat, 'alpha_test')
col = layout.column()
col.prop(mat, 'bump_uv_scale')
col = layout.column()
col.prop(mat, 'edge_fade_out')
col = layout.column()
col.prop(mat, 'depth_write')
col = layout.column()
col.prop(mat, 'sampler_clamp_uv_no_mip_0')
col = layout.column()
col.prop(mat, 'sampler_clamp_uv_no_mip_1')
col = layout.column()
col.prop(mat, 'num_textures')
col = layout.column()
col.prop(mat, 'texture_1')
col = layout.column()
col.prop(mat, 'secondary_texture_blend_mode')
col = layout.column()
col.prop(mat, 'tex_coord_mapper_0')
col = layout.column()
col.prop(mat, 'tex_coord_mapper_1')
col = layout.column()
col.prop(mat, 'tex_coord_transform_0')
col = layout.column()
col.prop(mat, 'tex_coord_transform_1')
col = layout.column()
col.prop(mat, 'environment_texture')
col = layout.column()
col.prop(mat, 'environment_mult')
col = layout.column()
col.prop(mat, 'recolor_texture')
col = layout.column()
col.prop(mat, 'recolor_mult')
col = layout.column()
col.prop(mat, 'use_recolor')
col = layout.column()
col.prop(mat, 'house_color_pulse')
col = layout.column()
col.prop(mat, 'scrolling_mask_texture')
col = layout.column()
col.prop(mat, 'tex_coord_transform_angle')
col = layout.column()
col.prop(mat, 'tex_coord_transform_u_0')
col = layout.column()
col.prop(mat, 'tex_coord_transform_v_0')
col = layout.column()
col.prop(mat, 'tex_coord_transform_u_1')
col = layout.column()
col.prop(mat, 'tex_coord_transform_v_1')
col = layout.column()
col.prop(mat, 'tex_coord_transform_u_2')
col = layout.column()
col.prop(mat, 'tex_coord_transform_v_2')
col = layout.column()
col.prop(mat, 'tex_ani_fps_NPR_lastFrame_frameOffset_0')
col = layout.column()
col.prop(mat, 'ion_hull_texture')
col = layout.column()
col.prop(mat, 'multi_texture_enable')
def register_node_groups():
dirname = os.path.dirname(__file__)
directory = os.path.join(dirname, 'node_group_templates')

for file in os.listdir(directory):
if not file.endswith(".xml"):
continue
NodeGroupCreator().create(directory, file)

CLASSES = (
ExportW3D,
ImportW3D,
ShaderProperties,
OBJECT_PROPERTIES_PANEL_PT_w3d,
BONE_PROPERTIES_PANEL_PT_w3d,
MATERIAL_PROPERTIES_PANEL_PT_w3d
)
VertexMaterialGroup.register(VertexMaterialGroup.name)


def register():
for class_ in CLASSES:
bpy.utils.register_class(class_)

Material.shader = PointerProperty(type=ShaderProperties)

bpy.types.TOPBAR_MT_file_import.append(menu_func_import)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)

# workaround to register the node group when the addon is active
# since bpy.data is not yet accessible
import time
from threading import Timer

Timer(1, register_node_groups, ()).start()


def unregister_node_groups():
dirname = os.path.dirname(__file__)
directory = os.path.join(dirname, 'node_group_templates')

for file in os.listdir(directory):
if not file.endswith(".xml"):
continue
NodeGroupCreator().unregister(directory, file)

VertexMaterialGroup.unregister(VertexMaterialGroup.name)


def unregister():
for class_ in reversed(CLASSES):
bpy.utils.unregister_class(class_)

bpy.types.TOPBAR_MT_file_import.remove(menu_func_import)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)

unregister_node_groups()


if __name__ == '__main__':
register()
112 changes: 112 additions & 0 deletions io_mesh_w3d/common/io_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# <pep8 compliant>
# Written by Stephan Vedder and Michael Schnabel

import io
import xml.etree.ElementTree as ET
from mathutils import Vector


def create_node(self, identifier):
return ET.SubElement(self, identifier)

def pretty_print(elem, level=0):
i = '\n' + level * ' '
if elem:
elem.text = i + ' '
elem.tail = i
for elem in elem:
pretty_print(elem, level + 1)
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i


def write(root, path):
pretty_print(root)
xml_spec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
data = bytes(xml_spec, 'utf-8') + ET.tostring(root)

file = open(path, 'wb')
file.write(data)
file.close()


def strip_namespaces(it):
for _, el in it:
el.tag = el.tag.split('}', 1)[-1]


def find_root(context, source):
try:
it = ET.iterparse(source)
strip_namespaces(it)
root = it.root
except BaseException:
if context is None:
print('ERROR: file: ' + source + ' does not contain valid XML data!')
else:
context.error('file: ' + source + ' does not contain valid XML data!')
return None
return root


def parse_value(xml_obj, cast_func=str):
return cast_func(xml_obj.text)


def create_value(value, parent, identifier):
xml_obj = create_node(parent, identifier)
xml_obj.text = str(value)


def parse_objects(parent, name, parse_func, par1=None):
result = []
objects = parent.findall(name)
if not objects:
return result
for obj in objects:
if par1 is not None:
result.append(parse_func(obj, par1))
else:
result.append(parse_func(obj))
return result


def create_object_list(parent, name, objects, write_func, par1=None):
xml_objects_list = create_node(parent, name)
for obj in objects:
if par1 is not None:
write_func(obj, xml_objects_list, par1)
else:
write_func(obj, xml_objects_list)


def format(value):
return '{:.6f}'.format(value)


def parse_vector2(xml_vector2):
return Vector((
float(xml_vector2.get('X', 0.0)),
float(xml_vector2.get('Y', 0.0))))


def create_vector2(vec2, parent, name):
vector = create_node(parent, name)
vector.set('X', format(vec2.x))
vector.set('Y', format(vec2.y))


def parse_vector(xml_vector):
return Vector((
float(xml_vector.get('X', 0.0)),
float(xml_vector.get('Y', 0.0)),
float(xml_vector.get('Z', 0.0))))


def create_vector(vec, parent, name):
vector = create_node(parent, name)
vector.set('X', format(vec.x))
vector.set('Y', format(vec.y))
vector.set('Z', format(vec.z))
Loading