Huge Amount of BugFix

-=-=-=-=-=-=-=-=-=-=-

-Fixes to Collada Exporter (avoid crash situtions)
-Fixed to Collada Importer (Fixed Animation Optimizer Bugs)
-Fixes to RigidBody/RigidBody2D body_enter/body_exit, was buggy
-Fixed ability for RigidBody/RigidBody2D to get contacts reported and bodyin/out in Kinematic mode.
-Added proper trigger support for 3D Physics shapes
-Changed proper value for Z-Offset in OmniLight
-Fixed spot attenuation bug in SpotLight
-Fixed some 3D and 2D spatial soudn bugs related to distance attenuation.
-Fixed bugs in EventPlayer (channels were muted by default)
-Fix in ButtonGroup (get nodes in group are now returned in order)
-Fixed Linear->SRGB Conversion, previous algo sucked, new algo works OK
-Changed SRGB->Linear conversion to use hardware if supported, improves texture quality a lot
-Fixed options for Y-Fov and X-Fov in camera, should be more intuitive.
-Fixed bugs related to viewports and transparency

Huge Amount of New Stuff:
-=-=-=-=-=-=-=-==-=-=-=-

-Ability to manually advance an AnimationPlayer that is inactive (with advance() function)
-More work in WinRT platform
-Added XY normalmap support, imports on this format by default. Reduces normlmap size and enables much nice compression using LATC
-Added Anisotropic filter support to textures, can be specified on import
-Added support for Non-Square, Isometric and Hexagonal tilemaps in TileMap.
-Added Isometric Dungeon demo.
-Added simple hexagonal map demo.
-Added Truck-Town demo. Shows how most types of joints and vehicles are used. Please somebody make a nicer town, this one is too hardcore.
-Added an Object-Picking API to both RigidBody and Area! (and relevant demo)
This commit is contained in:
Juan Linietsky 2014-10-03 00:10:51 -03:00
parent 870c075ebf
commit b24fe3dd20
84 changed files with 1660 additions and 344 deletions

View File

@ -856,6 +856,36 @@ Vector<int> _Geometry::triangulate_polygon(const Vector<Vector2>& p_polygon) {
return Geometry::triangulate_polygon(p_polygon);
}
Dictionary _Geometry::make_atlas(const Vector<Size2>& p_rects) {
Dictionary ret;
Vector<Size2i> rects;
for (int i=0; i<p_rects.size(); i++) {
rects.push_back(p_rects[i]);
};
Vector<Point2i> result;
Size2i size;
Geometry::make_atlas(rects, result, size);
Size2 r_size = size;
Vector<Point2> r_result;
for (int i=0; i<result.size(); i++) {
r_result.push_back(result[i]);
};
ret["points"] = r_result;
ret["size"] = r_size;
return ret;
};
void _Geometry::_bind_methods() {
@ -878,6 +908,7 @@ void _Geometry::_bind_methods() {
ObjectTypeDB::bind_method(_MD("triangulate_polygon","polygon"),&_Geometry::triangulate_polygon);
ObjectTypeDB::bind_method(_MD("make_atlas","sizes"),&_Geometry::make_atlas);
}

View File

@ -236,6 +236,8 @@ public:
Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
Dictionary make_atlas(const Vector<Size2>& p_rects);
_Geometry();
};

View File

@ -217,6 +217,14 @@ public:
*/
void convert( Format p_new_format );
Image converted(int p_new_format) {
ERR_FAIL_INDEX_V(p_new_format, FORMAT_MAX, Image());
Image ret = *this;
ret.convert((Format)p_new_format);
return ret;
};
/**
* Get the current image format.
*/

View File

@ -1004,3 +1004,134 @@ DVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, in
}
struct _AtlasWorkRect {
Size2i s;
Point2i p;
int idx;
_FORCE_INLINE_ bool operator<(const _AtlasWorkRect& p_r) const { return s.width > p_r.s.width; };
};
struct _AtlasWorkRectResult {
Vector<_AtlasWorkRect> result;
int max_w;
int max_h;
};
void Geometry::make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size) {
//super simple, almost brute force scanline stacking fitter
//it's pretty basic for now, but it tries to make sure that the aspect ratio of the
//resulting atlas is somehow square. This is necesary because video cards have limits
//on texture size (usually 2048 or 4096), so the more square a texture, the more chances
//it will work in every hardware.
// for example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a
// 256x8192 atlas (won't work anywhere).
ERR_FAIL_COND(p_rects.size()==0);
Vector<_AtlasWorkRect> wrects;
wrects.resize(p_rects.size());
for(int i=0;i<p_rects.size();i++) {
wrects[i].s=p_rects[i];
wrects[i].idx=i;
}
wrects.sort();
int widest = wrects[0].s.width;
Vector<_AtlasWorkRectResult> results;
for(int i=0;i<=12;i++) {
int w = 1<<i;
int max_h=0;
int max_w=0;
if ( w < widest )
continue;
Vector<int> hmax;
hmax.resize(w);
for(int j=0;j<w;j++)
hmax[j]=0;
//place them
int ofs=0;
int limit_h=0;
for(int j=0;j<wrects.size();j++) {
if (ofs+wrects[j].s.width > w) {
ofs=0;
}
int from_y=0;
for(int k=0;k<wrects[j].s.width;k++) {
if (hmax[ofs+k] > from_y)
from_y=hmax[ofs+k];
}
wrects[j].p.x=ofs;
wrects[j].p.y=from_y;
int end_h = from_y+wrects[j].s.height;
int end_w = ofs+wrects[j].s.width;
if (ofs==0)
limit_h=end_h;
for(int k=0;k<wrects[j].s.width;k++) {
hmax[ofs+k]=end_h;
}
if (end_h > max_h)
max_h=end_h;
if (end_w > max_w)
max_w=end_w;
if (ofs==0 || end_h>limit_h ) //while h limit not reched, keep stacking
ofs+=wrects[j].s.width;
}
_AtlasWorkRectResult result;
result.result=wrects;
result.max_h=max_h;
result.max_w=max_w;
results.push_back(result);
}
//find the result with the best aspect ratio
int best=-1;
float best_aspect=1e20;
for(int i=0;i<results.size();i++) {
float h = nearest_power_of_2(results[i].max_h);
float w = nearest_power_of_2(results[i].max_w);
float aspect = h>w ? h/w : w/h;
if (aspect < best_aspect) {
best=i;
best_aspect=aspect;
}
}
r_result.resize(p_rects.size());
for(int i=0;i<p_rects.size();i++) {
r_result[ results[best].result[i].idx ]=results[best].result[i].p;
}
r_size=Size2(results[best].max_w,results[best].max_h );
}

View File

@ -827,6 +827,8 @@ public:
static DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
static DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
};

View File

@ -515,7 +515,7 @@ static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Varian
#define VCALL_PTR0R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(); }
#define VCALL_PTR1(m_type,m_method)\
static void _call_##m_type##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
#define VCALL_PTR1R(m_type,m_method)\
static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Variant** p_args) { r_ret=reinterpret_cast<m_type*>(p_self._data._ptr)->m_method(*p_args[0]); }
#define VCALL_PTR2(m_type,m_method)\
@ -551,6 +551,7 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
VCALL_PTR3R(Image, resized);
VCALL_PTR0R(Image, get_data);
VCALL_PTR3(Image, blit_rect);
VCALL_PTR1R(Image, converted);
VCALL_PTR0R( AABB, get_area );
VCALL_PTR0R( AABB, has_no_area );
@ -605,6 +606,25 @@ static void _call_##m_type##_##m_method(Variant& r_ret,Variant& p_self,const Var
}
}
static void _call_Matrix32_basis_xform(Variant& r_ret,Variant& p_self,const Variant** p_args) {
switch(p_args[0]->type) {
case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform( p_args[0]->operator Vector2()); return;
default: r_ret=Variant();
}
}
static void _call_Matrix32_basis_xform_inv(Variant& r_ret,Variant& p_self,const Variant** p_args) {
switch(p_args[0]->type) {
case Variant::VECTOR2: r_ret=reinterpret_cast<Matrix32*>(p_self._data._ptr)->basis_xform_inv( p_args[0]->operator Vector2()); return;
default: r_ret=Variant();
}
}
VCALL_PTR0R( Matrix3, inverse );
VCALL_PTR0R( Matrix3, transposed );
@ -1313,6 +1333,7 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC3(IMAGE, IMAGE, Image, resized, INT, "x", INT, "y", INT, "interpolation", varray(((int)Image::INTERPOLATE_BILINEAR)));
ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray());
ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0));
ADDFUNC1(IMAGE, IMAGE, Image, converted, INT, "format", varray(0));
ADDFUNC0(_RID,INT,RID,get_id,varray());
@ -1430,6 +1451,8 @@ _VariantCall::addfunc(Variant::m_vtype,Variant::m_ret,_SCS(#m_method),VCALL(m_cl
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,translated,VECTOR2,"offset",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform,NIL,"v",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform_inv,NIL,"v",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform,NIL,"v",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,basis_xform_inv,NIL,"v",varray());
ADDFUNC2(MATRIX32,MATRIX32,Matrix32,interpolate_with,MATRIX32,"m",REAL,"c",varray());
ADDFUNC0(MATRIX3,MATRIX3,Matrix3,inverse,varray());

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,7 @@
[application]
main_scene="res://truck_scene.scn"
[rasterizer]
shadow_filter=3

View File

@ -0,0 +1,69 @@
extends Camera
# member variables here, example:
# var a=2
# var b="textvar"
var collision_exception=[]
export var min_distance=0.5
export var max_distance=4.0
export var angle_v_adjust=0.0
export var autoturn_ray_aperture=25
export var autoturn_speed=50
var max_height = 2.0
var min_height = 0
func _fixed_process(dt):
var target = get_parent().get_global_transform().origin
var pos = get_global_transform().origin
var up = Vector3(0,1,0)
var delta = pos - target
#regular delta follow
#check ranges
if (delta.length() < min_distance):
delta = delta.normalized() * min_distance
elif (delta.length() > max_distance):
delta = delta.normalized() * max_distance
#check upper and lower height
if ( delta.y > max_height):
delta.y = max_height
if ( delta.y < min_height):
delta.y = min_height
pos = target + delta
look_at_from_pos(pos,target,up)
#turn a little up or down
var t = get_transform()
t.basis = Matrix3(t.basis[0],deg2rad(angle_v_adjust)) * t.basis
set_transform(t)
func _ready():
#find collision exceptions for ray
var node = self
while(node):
if (node extends RigidBody):
collision_exception.append(node.get_rid())
break
else:
node=node.get_parent()
# Initalization here
set_fixed_process(true)
#this detaches the camera transform from the parent spatial node
set_as_toplevel(true)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,54 @@
extends VehicleBody
# member variables here, example:
# var a=2
# var b="textvar"
const STEER_SPEED=1
const STEER_LIMIT=0.4
var steer_angle=0
var steer_target=0
export var engine_force=40
func _fixed_process(delta):
if (Input.is_action_pressed("ui_left")):
steer_target=-STEER_LIMIT
elif (Input.is_action_pressed("ui_right")):
steer_target=STEER_LIMIT
else:
steer_target=0
if (Input.is_action_pressed("ui_up")):
set_engine_force(engine_force)
else:
set_engine_force(0)
if (Input.is_action_pressed("ui_down")):
set_brake(1)
else:
set_brake(0.0)
if (steer_target < steer_angle):
steer_angle -= STEER_SPEED*delta
if (steer_target > steer_angle):
steer_angle=steer_target
elif (steer_target > steer_angle):
steer_angle += STEER_SPEED*delta
if (steer_target < steer_angle):
steer_angle=steer_target
set_steering(steer_angle)
func _ready():
# Initalization here
set_fixed_process(true)
pass

View File

@ -86,12 +86,18 @@ public:
return fa->get_pos();
};
TPDataFA(String p_path) {
TPDataFA(const String& p_path) {
fa = FileAccess::open(p_path, FileAccess::READ);
data_name = "File: " + p_path;
};
TPDataFA(FileAccess* p_fa, const String& p_path) {
fa = p_fa;
data_name = "File: " + p_path;
};
~TPDataFA() {
if (fa)
@ -366,6 +372,10 @@ void VideoStreamTheoraplayer::update(float p_time) {
void VideoStreamTheoraplayer::set_file(const String& p_file) {
FileAccess* f = FileAccess::open(p_file, FileAccess::READ);
if (!f || !f->is_open())
return;
if (!audio_factory) {
audio_factory = memnew(TPAudioGodotFactory);
};
@ -377,10 +387,11 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) {
std::string file = p_file.replace("res://", "").utf8().get_data();
clip = mgr->createVideoClip(file);
memdelete(f);
} else {
TheoraDataSource* ds = memnew(TPDataFA(p_file));
TheoraDataSource* ds = memnew(TPDataFA(f, p_file));
try {
clip = mgr->createVideoClip(ds);

View File

@ -3,6 +3,9 @@ Import('env')
files = [
'thread_winrt.cpp',
# '#platform/windows/stream_peer_winsock.cpp',
'gl_context_egl.cpp',
'app.cpp',
'os_winrt.cpp',
]
env.Program('#bin/godot_rt.exe', files)
env.Program('#bin/godot_rt', files)

162
platform/winrt/app.cpp Normal file
View File

@ -0,0 +1,162 @@
//
// This file demonstrates how to initialize EGL in a Windows Store app, using ICoreWindow.
//
#include "app.h"
#include "main/main.h"
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Display;
using namespace Microsoft::WRL;
using namespace Platform;
using namespace $ext_safeprojectname$;
// Helper to convert a length in device-independent pixels (DIPs) to a length in physical pixels.
inline float ConvertDipsToPixels(float dips, float dpi)
{
static const float dipsPerInch = 96.0f;
return floor(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
}
// Implementation of the IFrameworkViewSource interface, necessary to run our app.
ref class HelloTriangleApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
{
public:
virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView()
{
return ref new App();
}
};
// The main function creates an IFrameworkViewSource for our app, and runs the app.
[Platform::MTAThread]
int main(Platform::Array<Platform::String^>^)
{
auto helloTriangleApplicationSource = ref new HelloTriangleApplicationSource();
CoreApplication::Run(helloTriangleApplicationSource);
return 0;
}
App::App() :
mWindowClosed(false),
mWindowVisible(true),
mWindowWidth(0),
mWindowHeight(0),
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
mEglSurface(EGL_NO_SURFACE)
{
}
// The first method called when the IFrameworkView is being created.
void App::Initialize(CoreApplicationView^ applicationView)
{
// Register event handlers for app lifecycle. This example includes Activated, so that we
// can make the CoreWindow active and start rendering on the window.
applicationView->Activated +=
ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
// Logic for other event handlers could go here.
// Information about the Suspending and Resuming event handlers can be found here:
// http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh994930.aspx
os = new OSWinrt;
}
// Called when the CoreWindow object is created (or re-created).
void App::SetWindow(CoreWindow^ window)
{
window->VisibilityChanged +=
ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
window->Closed +=
ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
window->SizeChanged +=
ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
#if !(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
// Disable all pointer visual feedback for better performance when touching.
// This is not supported on Windows Phone applications.
auto pointerVisualizationSettings = PointerVisualizationSettings::GetForCurrentView();
pointerVisualizationSettings->IsContactFeedbackEnabled = false;
pointerVisualizationSettings->IsBarrelButtonFeedbackEnabled = false;
#endif
// The CoreWindow has been created, so EGL can be initialized.
ContextEGL* context = memnew(ContextEGL(window));
os->set_gl_context(context);
UpdateWindowSize(Size(window->Bounds.Width, window->Bounds.Height));
}
// Initializes scene resources
void App::Load(Platform::String^ entryPoint)
{
char** args = {NULL};
Main::setup("winrt", 0, args);
}
// This method is called after the window becomes active.
void App::Run()
{
if (Main::start())
os->run();
}
// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
// class is torn down while the app is in the foreground.
void App::Uninitialize()
{
Main::cleanup();
delete os;
}
// Application lifecycle event handler.
void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
{
// Run() won't start until the CoreWindow is activated.
CoreWindow::GetForCurrentThread()->Activate();
}
// Window event handlers.
void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
{
mWindowVisible = args->Visible;
}
void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
{
mWindowClosed = true;
}
void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
{
#if (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
// On Windows 8.1, apps are resized when they are snapped alongside other apps, or when the device is rotated.
// The default framebuffer will be automatically resized when either of these occur.
// In particular, on a 90 degree rotation, the default framebuffer's width and height will switch.
UpdateWindowSize(args->Size);
#else if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
// On Windows Phone 8.1, the window size changes when the device is rotated.
// The default framebuffer will not be automatically resized when this occurs.
// It is therefore up to the app to handle rotation-specific logic in its rendering code.
#endif
}
void App::UpdateWindowSize(Size size)
{
/*
DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
Size pixelSize(ConvertDipsToPixels(size.Width, currentDisplayInformation->LogicalDpi), ConvertDipsToPixels(size.Height, currentDisplayInformation->LogicalDpi));
mWindowWidth = static_cast<GLsizei>(pixelSize.Width);
mWindowHeight = static_cast<GLsizei>(pixelSize.Height);
*/
}

51
platform/winrt/app.h Normal file
View File

@ -0,0 +1,51 @@
#pragma once
#include <string>
#include <wrl.h>
#include "os_winrt.h"
#include "GLES2/gl2.h"
namespace $ext_safeprojectname$
{
ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView
{
public:
App();
// IFrameworkView Methods.
virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
virtual void Load(Platform::String^ entryPoint);
virtual void Run();
virtual void Uninitialize();
private:
void RecreateRenderer();
// Application lifecycle event handlers.
void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
// Window event handlers.
void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
void UpdateWindowSize(Windows::Foundation::Size size);
void InitializeEGL(Windows::UI::Core::CoreWindow^ window);
void CleanupEGL();
bool mWindowClosed;
bool mWindowVisible;
GLsizei mWindowWidth;
GLsizei mWindowHeight;
EGLDisplay mEglDisplay;
EGLContext mEglContext;
EGLSurface mEglSurface;
OSWinrt* os;
};
}

View File

@ -57,13 +57,13 @@ def configure(env):
env.Append(CCFLAGS=['-g','-pg'])
env.Append(LINKFLAGS=['-pg'])
env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/ZW', '/EHsc'])
env.Append(CXXFLAGS=['/TP'])
env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc'])
env.Append(CXXFLAGS=['/TP', '/ZW'])
env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
#env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
env.Append(CCFLAGS=['/DWINRT_ENABLED'])
env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP'])
env.Append(CCFLAGS=['/DWINAPI_FAMILY=WINAPI_FAMILY_APP', '/D_WIN32_WINNT=0x0603', '/DNTDDI_VERSION=0x06030000'])
env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
#env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])

View File

@ -0,0 +1,151 @@
#include "gl_context_egl.h"
using namespace Platform;
void ContextEGL::release_current() {
eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, mEglContext);
};
void ContextEGL::make_current() {
eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
};
int ContextEGL::get_window_width() {
return width;
};
int ContextEGL::get_window_height() {
return height;
};
void ContextEGL::swap_buffers() {
if (eglSwapBuffers(mEglDisplay, mEglSurface) != EGL_TRUE)
{
cleanup();
window = CoreWindow::GetForCurrentThread();
initialize();
// tell rasterizer to reload textures and stuff?
}
};
Error ContextEGL::initialize() {
EGLint configAttribList[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, 0,
EGL_NONE
};
EGLint surfaceAttribList[] = {
EGL_NONE, EGL_NONE
};
EGLint numConfigs = 0;
EGLint majorVersion = 1;
EGLint minorVersion = 0;
EGLDisplay display = EGL_NO_DISPLAY;
EGLContext context = EGL_NO_CONTEXT;
EGLSurface surface = EGL_NO_SURFACE;
EGLConfig config = nullptr;
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
try {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY)
{
throw Exception::CreateException(E_FAIL, L"Failed to get default EGL display");
}
if (eglInitialize(display, &majorVersion, &minorVersion) == EGL_FALSE)
{
throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
}
if (eglGetConfigs(display, NULL, 0, &numConfigs) == EGL_FALSE)
{
throw Exception::CreateException(E_FAIL, L"Failed to get EGLConfig count");
}
if (eglChooseConfig(display, configAttribList, &config, 1, &numConfigs) == EGL_FALSE)
{
throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig count");
}
surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(window), surfaceAttribList);
if (surface == EGL_NO_SURFACE)
{
throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface");
}
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
if (context == EGL_NO_CONTEXT)
{
throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
}
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
{
throw Exception::CreateException(E_FAIL, L"Failed to make fullscreen EGLSurface current");
}
} catch (...) {
return FAILED;
};
mEglDisplay = display;
mEglSurface = surface;
mEglContext = context;
eglQuerySurface(display,surface,EGL_WIDTH,&width);
eglQuerySurface(display,surface,EGL_HEIGHT,&height);
return OK;
};
void ContextEGL::cleanup() {
if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE)
{
eglDestroySurface(mEglDisplay, mEglSurface);
mEglSurface = EGL_NO_SURFACE;
}
if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT)
{
eglDestroyContext(mEglDisplay, mEglContext);
mEglContext = EGL_NO_CONTEXT;
}
if (mEglDisplay != EGL_NO_DISPLAY)
{
eglTerminate(mEglDisplay);
mEglDisplay = EGL_NO_DISPLAY;
}
};
ContextEGL::ContextEGL(CoreWindow^ p_window) :
mEglDisplay(EGL_NO_DISPLAY),
mEglContext(EGL_NO_CONTEXT),
mEglSurface(EGL_NO_SURFACE)
{
window = p_window;
};
ContextEGL::~ContextEGL() {
cleanup();
};

View File

@ -0,0 +1,44 @@
#ifndef CONTEXT_EGL_H
#define CONTEXT_EGL_H
#include <wrl.h>
#include "os/os.h"
#include "EGL/egl.h"
#include "error_list.h"
#include "drivers/gl_context/context_gl.h"
using namespace Windows::UI::Core;
class ContextEGL : public ContextGL {
CoreWindow^ window;
EGLDisplay mEglDisplay;
EGLContext mEglContext;
EGLSurface mEglSurface;
EGLint width;
EGLint height;
public:
virtual void release_current();
virtual void make_current();
virtual int get_window_width();
virtual int get_window_height();
virtual void swap_buffers();
virtual Error initialize();
void cleanup();
ContextEGL(CoreWindow^ p_window);
~ContextEGL();
};
#endif

View File

@ -1,5 +1,5 @@
/*************************************************************************/
/* os_windows.cpp */
/* os_winrt.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@ -28,12 +28,12 @@
/*************************************************************************/
#include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles1/rasterizer_gles1.h"
#include "os_windows.h"
#include "os_winrt.h"
#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
#include "drivers/unix/memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h"
#include "drivers/windows/thread_windows.h"
#include "drivers/windows/semaphore_windows.h"
#include "thread_winrt.h"
//#include "drivers/windows/semaphore_windows.h"
#include "drivers/windows/mutex_windows.h"
#include "main/main.h"
#include "drivers/windows/file_access_windows.h"
@ -44,14 +44,22 @@
#include "servers/audio/audio_server_sw.h"
#include "servers/visual/visual_server_wrap_mt.h"
#include "tcp_server_winsock.h"
#include "stream_peer_winsock.h"
#include "os/pc_joystick_map.h"
#include "lang_table.h"
#include "os/memory_pool_dynamic_prealloc.h"
#include "globals.h"
#include "io/marshalls.h"
#include <wrl.h>
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
using namespace Windows::Foundation;
using namespace Windows::Graphics::Display;
using namespace Microsoft::WRL;
int OSWinrt::get_video_driver_count() const {
return 2;
@ -129,58 +137,17 @@ bool OSWinrt::can_draw() const {
};
void OSWinrt::_touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam) {
void OSWinrt::set_gl_context(ContextEGL* p_context) {
InputEvent event;
event.type = InputEvent::SCREEN_TOUCH;
event.ID=++last_id;
event.screen_touch.index = idx;
switch (uMsg) {
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN: {
event.screen_touch.pressed = true;
} break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP: {
event.screen_touch.pressed = false;
} break;
};
event.screen_touch.x=GET_X_LPARAM(lParam);
event.screen_touch.y=GET_Y_LPARAM(lParam);
if (main_loop) {
input->parse_input_event(event);
}
gl_context = p_context;
};
void OSWinrt::_drag_event(int idx,UINT uMsg, WPARAM wParam, LPARAM lParam) {
InputEvent event;
event.type = InputEvent::SCREEN_DRAG;
event.ID=++last_id;
event.screen_drag.index = idx;
event.screen_drag.x=GET_X_LPARAM(lParam);
event.screen_drag.y=GET_Y_LPARAM(lParam);
if (main_loop)
input->parse_input_event(event);
};
void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
main_loop=NULL;
outside=true;
gl_context->initialize();
visual_server = memnew( VisualServerRaster(rasterizer) );
if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) {
@ -222,6 +189,7 @@ void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_aud
void OSWinrt::set_clipboard(const String& p_text) {
/*
if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard.");
ERR_FAIL();
@ -255,10 +223,12 @@ void OSWinrt::set_clipboard(const String& p_text) {
SetClipboardData(CF_TEXT, mem);
CloseClipboard();
*/
};
String OSWinrt::get_clipboard() const {
/*
String ret;
if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard.");
@ -295,6 +265,8 @@ String OSWinrt::get_clipboard() const {
CloseClipboard();
return ret;
*/
return "";
};
@ -327,10 +299,6 @@ void OSWinrt::finalize() {
if (rasterizer)
memdelete(rasterizer);
if (user_proc) {
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
};
spatial_sound_server->finish();
memdelete(spatial_sound_server);
spatial_sound_2d_server->finish();
@ -355,16 +323,11 @@ void OSWinrt::finalize() {
}
void OSWinrt::finalize_core() {
memdelete(process_map);
if (mempool_dynamic)
memdelete( mempool_dynamic );
if (mempool_static)
delete mempool_static;
TCPServerWinsock::cleanup();
StreamPeerWinsock::cleanup();
}
void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
@ -399,9 +362,6 @@ void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
void OSWinrt::alert(const String& p_alert,const String& p_title) {
if (!is_no_window_mode_enabled())
MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
else
print_line("ALERT: "+p_alert);
}
@ -445,8 +405,6 @@ void OSWinrt::get_fullscreen_mode_list(List<VideoMode> *p_list,int p_screen) con
void OSWinrt::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) {
HANDLE hCon=GetStdHandle(STD_OUTPUT_HANDLE);
if (!hCon || hCon==INVALID_HANDLE_VALUE) {
if (p_rationale && p_rationale[0]) {
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
@ -457,59 +415,6 @@ void OSWinrt::print_error(const char* p_function,const char* p_file,int p_line,c
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
}
} else {
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
GetConsoleScreenBufferInfo(hCon,&sbi);
SetConsoleTextAttribute(hCon,sbi.wAttributes);
uint32_t basecol=0;
switch(p_type) {
case ERR_ERROR: basecol = FOREGROUND_RED; break;
case ERR_WARNING: basecol = FOREGROUND_RED|FOREGROUND_GREEN; break;
case ERR_SCRIPT: basecol = FOREGROUND_GREEN; break;
}
if (p_rationale && p_rationale[0]) {
SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
switch(p_type) {
case ERR_ERROR: print("ERROR: "); break;
case ERR_WARNING: print("WARNING: "); break;
case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
}
SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
print(" %s\n",p_rationale);
SetConsoleTextAttribute(hCon,basecol);
print("At: ");
SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
print(" %s:%i\n",p_file,p_line);
} else {
SetConsoleTextAttribute(hCon,basecol|FOREGROUND_INTENSITY);
switch(p_type) {
case ERR_ERROR: print("ERROR: %s: ",p_function); break;
case ERR_WARNING: print("WARNING: %s: ",p_function); break;
case ERR_SCRIPT: print("SCRIPT ERROR: %s: ",p_function); break;
}
SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY);
print(" %s\n",p_code);
SetConsoleTextAttribute(hCon,basecol);
print("At: ");
SetConsoleTextAttribute(hCon,FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
print(" %s:%i\n",p_file,p_line);
}
SetConsoleTextAttribute(hCon,sbi.wAttributes);
}
}
@ -566,10 +471,10 @@ uint64_t OSWinrt::get_unix_time() const {
void OSWinrt::delay_usec(uint32_t p_usec) const {
if (p_usec < 1000)
Sleep(1);
else
Sleep(p_usec / 1000);
int msec = p_usec < 1000 ? 1 : p_usec / 1000;
// no Sleep()
WaitForSingleObjectEx(GetCurrentThread(), msec, false);
}
uint64_t OSWinrt::get_ticks_usec() const {
@ -607,19 +512,12 @@ Error OSWinrt::kill(const ProcessID& p_pid) {
Error OSWinrt::set_cwd(const String& p_cwd) {
if (_wchdir(p_cwd.c_str())!=0)
return ERR_CANT_OPEN;
return OK;
}
String OSWinrt::get_executable_path() const {
wchar_t bufname[4096];
GetModuleFileNameW(NULL,bufname,4096);
String s= bufname;
print_line("EXEC PATHPó: "+s);
return s;
return "";
}
void OSWinrt::set_icon(const Image& p_icon) {
@ -629,25 +527,16 @@ void OSWinrt::set_icon(const Image& p_icon) {
bool OSWinrt::has_environment(const String& p_var) const {
return getenv(p_var.utf8().get_data()) != NULL;
return false;
};
String OSWinrt::get_environment(const String& p_var) const {
char* val = getenv(p_var.utf8().get_data());
if (val)
return val;
return "";
};
String OSWinrt::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
return fgets(buff,1024,stdin);
};
return String();
}
@ -665,23 +554,22 @@ Error OSWinrt::shell_open(String p_uri) {
String OSWinrt::get_locale() const {
Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
return language.Data();
return language->Data();
}
void OSWinrt::release_rendering_thread() {
//gl_context->release_current();
gl_context->release_current();
}
void OSWinrt::make_rendering_thread() {
//gl_context->make_current();
gl_context->make_current();
}
void OSWinrt::swap_buffers() {
//gl_context->swap_buffers();
gl_context->swap_buffers();
}
@ -699,6 +587,7 @@ void OSWinrt::run() {
while (!force_quit) {
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
process_events(); // get rid of pending events
if (Main::iteration()==true)
break;
@ -724,7 +613,7 @@ String OSWinrt::get_data_dir() const {
}
OSWinrt::OSWinrt(HINSTANCE _hInstance) {
OSWinrt::OSWinrt() {
key_event_pos=0;
force_quit=false;
@ -743,6 +632,8 @@ OSWinrt::OSWinrt(HINSTANCE _hInstance) {
stdo=fopen("stdout.txt","wb");
#endif
gl_context = NULL;
}

View File

@ -41,11 +41,10 @@
#include "servers/spatial_sound_2d/spatial_sound_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "gl_context_egl.h"
#include <windows.h>
#include "key_mapping_win.h"
#include <windowsx.h>
#include <io.h>
#include <fcntl.h>
@ -93,6 +92,8 @@ class OSWinrt : public OS {
Physics2DServer *physics_2d_server;
int pressrc;
ContextEGL* gl_context;
struct Joystick {
int id;
@ -224,6 +225,8 @@ public:
virtual void move_window_to_foreground();
virtual String get_data_dir() const;
void set_gl_context(ContextEGL* p_context);
virtual void release_rendering_thread();
virtual void make_rendering_thread();
virtual void swap_buffers();

View File

@ -106,9 +106,9 @@ Ref<TileSet> TileMap::get_tileset() const {
return tile_set;
}
void TileMap::set_cell_size(int p_size) {
void TileMap::set_cell_size(Size2 p_size) {
ERR_FAIL_COND(p_size<1);
ERR_FAIL_COND(p_size.x<1 || p_size.y<1);
_clear_quadrants();
cell_size=p_size;
@ -117,7 +117,7 @@ void TileMap::set_cell_size(int p_size) {
}
int TileMap::get_cell_size() const {
Size2 TileMap::get_cell_size() const {
return cell_size;
}
@ -171,6 +171,7 @@ void TileMap::_update_dirty_quadrants() {
VisualServer *vs = VisualServer::get_singleton();
Physics2DServer *ps = Physics2DServer::get_singleton();
Vector2 tofs = get_cell_draw_offset();
while (dirty_quadrant_list.first()) {
@ -189,7 +190,7 @@ void TileMap::_update_dirty_quadrants() {
Ref<Texture> tex = tile_set->tile_get_texture(c.id);
Vector2 tile_ofs = tile_set->tile_get_texture_offset(c.id);
Vector2 offset = Point2( E->key().x, E->key().y )*cell_size - q.pos;
Vector2 offset = _map_to_world(E->key().x, E->key().y) - q.pos + tofs;
if (!tex.is_valid())
continue;
@ -299,7 +300,11 @@ void TileMap::_recompute_rect_cache() {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) {
Rect2 r( Point2(E->key().x, E->key().y)*cell_size*quadrant_size, Size2(1,1)*cell_size*quadrant_size );
Rect2 r;
r.pos=_map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size);
r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size) );
r.expand_to( _map_to_world(E->key().x*quadrant_size+quadrant_size, E->key().y*quadrant_size+quadrant_size) );
r.expand_to( _map_to_world(E->key().x*quadrant_size, E->key().y*quadrant_size+quadrant_size) );
if (E==quadrant_map.front())
r_total=r;
else
@ -323,8 +328,10 @@ void TileMap::_recompute_rect_cache() {
Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
Matrix32 xform;
xform.set_origin(Point2(p_qk.x,p_qk.y)*quadrant_size*cell_size);
//xform.set_origin(Point2(p_qk.x,p_qk.y)*cell_size*quadrant_size);
Quadrant q;
q.pos = _map_to_world(p_qk.x*quadrant_size,p_qk.y*quadrant_size);
xform.set_origin( q.pos );
q.canvas_item = VisualServer::get_singleton()->canvas_item_create();
VisualServer::get_singleton()->canvas_item_set_parent( q.canvas_item, get_canvas_item() );
VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform );
@ -341,7 +348,6 @@ Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const
}
Physics2DServer::get_singleton()->body_set_state(q.static_body,Physics2DServer::BODY_STATE_TRANSFORM,xform);
q.pos=Vector2(p_qk.x,p_qk.y)*quadrant_size*cell_size;
rect_cache_dirty=true;
quadrant_order_dirty=true;
@ -478,8 +484,11 @@ void TileMap::_recreate_quadrants() {
}
Q->get().cells.insert(E->key());
_make_quadrant_dirty(Q);
}
}
void TileMap::_clear_quadrants() {
@ -614,6 +623,152 @@ uint32_t TileMap::get_collision_layer_mask() const {
return collision_layer;
}
void TileMap::set_mode(Mode p_mode) {
_clear_quadrants();
mode=p_mode;
_recreate_quadrants();
emit_signal("settings_changed");
}
TileMap::Mode TileMap::get_mode() const {
return mode;
}
void TileMap::set_half_offset(HalfOffset p_half_offset) {
_clear_quadrants();
half_offset=p_half_offset;
_recreate_quadrants();
emit_signal("settings_changed");
}
Vector2 TileMap::get_cell_draw_offset() const {
switch(mode) {
case MODE_SQUARE: {
return Vector2();
} break;
case MODE_ISOMETRIC: {
return Vector2(-cell_size.x*0.5,0);
} break;
case MODE_CUSTOM: {
Vector2 min;
min.x = MIN(custom_transform[0].x,min.x);
min.y = MIN(custom_transform[0].y,min.y);
min.x = MIN(custom_transform[1].x,min.x);
min.y = MIN(custom_transform[1].y,min.y);
return min;
} break;
}
return Vector2();
}
TileMap::HalfOffset TileMap::get_half_offset() const {
return half_offset;
}
Matrix32 TileMap::get_cell_transform() const {
switch(mode) {
case MODE_SQUARE: {
Matrix32 m;
m[0]*=cell_size.x;
m[1]*=cell_size.y;
return m;
} break;
case MODE_ISOMETRIC: {
//isometric only makes sense when y is positive in both x and y vectors, otherwise
//the drawing of tiles will overlap
Matrix32 m;
m[0]=Vector2(cell_size.x*0.5,cell_size.y*0.5);
m[1]=Vector2(-cell_size.x*0.5,cell_size.y*0.5);
return m;
} break;
case MODE_CUSTOM: {
return custom_transform;
} break;
}
return Matrix32();
}
void TileMap::set_custom_transform(const Matrix32& p_xform) {
_clear_quadrants();
custom_transform=p_xform;
_recreate_quadrants();
emit_signal("settings_changed");
}
Matrix32 TileMap::get_custom_transform() const{
return custom_transform;
}
Vector2 TileMap::_map_to_world(int x,int y,bool p_ignore_ofs) const {
Vector2 ret = get_cell_transform().xform(Vector2(x,y));
if (!p_ignore_ofs) {
switch(half_offset) {
case HALF_OFFSET_X: {
if (ABS(y)&1) {
ret+=get_cell_transform()[0]*0.5;
}
} break;
case HALF_OFFSET_Y: {
if (ABS(x)&1) {
ret+=get_cell_transform()[1]*0.5;
}
} break;
default: {}
}
}
return ret;
}
Vector2 TileMap::map_to_world(const Vector2& p_pos,bool p_ignore_ofs) const {
return _map_to_world(p_pos.x,p_pos.y,p_ignore_ofs);
}
Vector2 TileMap::world_to_map(const Vector2& p_pos) const{
Vector2 ret = get_cell_transform().affine_inverse().xform(p_pos);
switch(half_offset) {
case HALF_OFFSET_X: {
if (int(ret.y)&1) {
ret.x-=0.5;
}
} break;
case HALF_OFFSET_Y: {
if (int(ret.x)&1) {
ret.y-=0.5;
}
} break;
default: {}
}
return ret.floor();
}
void TileMap::_bind_methods() {
@ -621,10 +776,21 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_tileset);
ObjectTypeDB::bind_method(_MD("set_mode","mode"),&TileMap::set_mode);
ObjectTypeDB::bind_method(_MD("get_mode"),&TileMap::get_mode);
ObjectTypeDB::bind_method(_MD("set_half_offset","half_offset"),&TileMap::set_half_offset);
ObjectTypeDB::bind_method(_MD("get_half_offset"),&TileMap::get_half_offset);
ObjectTypeDB::bind_method(_MD("set_custom_transform","custom_transform"),&TileMap::set_custom_transform);
ObjectTypeDB::bind_method(_MD("get_custom_transform"),&TileMap::get_custom_transform);
ObjectTypeDB::bind_method(_MD("set_cell_size","size"),&TileMap::set_cell_size);
ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_cell_size);
ObjectTypeDB::bind_method(_MD("_set_old_cell_size","size"),&TileMap::_set_old_cell_size);
ObjectTypeDB::bind_method(_MD("_get_old_cell_size"),&TileMap::_get_old_cell_size);
ObjectTypeDB::bind_method(_MD("set_quadrant_size","size"),&TileMap::set_quadrant_size);
ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_quadrant_size);
@ -650,6 +816,9 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("clear"),&TileMap::clear);
ObjectTypeDB::bind_method(_MD("map_to_world","mappos","ignore_half_ofs"),&TileMap::map_to_world,DEFVAL(false));
ObjectTypeDB::bind_method(_MD("world_to_map","worldpos"),&TileMap::world_to_map);
ObjectTypeDB::bind_method(_MD("_clear_quadrants"),&TileMap::_clear_quadrants);
ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_quadrants);
@ -657,17 +826,28 @@ void TileMap::_bind_methods() {
ObjectTypeDB::bind_method(_MD("_set_tile_data"),&TileMap::_set_tile_data);
ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_tile_data);
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell_size",PROPERTY_HINT_RANGE,"1,8192,1",0),_SCS("_set_old_cell_size"),_SCS("_get_old_cell_size"));
ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"cell/size",PROPERTY_HINT_RANGE,"1,8192,1"),_SCS("set_cell_size"),_SCS("get_cell_size"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/quadrant_size",PROPERTY_HINT_RANGE,"1,128,1"),_SCS("set_quadrant_size"),_SCS("get_quadrant_size"));
ADD_PROPERTY( PropertyInfo(Variant::MATRIX32,"cell/custom_transform"),_SCS("set_custom_transform"),_SCS("get_custom_transform"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"cell/half_offset",PROPERTY_HINT_ENUM,"Offset X,Offset Y,Disabled"),_SCS("set_half_offset"),_SCS("get_half_offset"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/friction",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_friction"),_SCS("get_collision_friction"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"collision/bounce",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_collision_bounce"),_SCS("get_collision_bounce"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"collision/layers",PROPERTY_HINT_ALL_FLAGS),_SCS("set_collision_layer_mask"),_SCS("get_collision_layer_mask"));
ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"tile_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_tile_data"),_SCS("_get_tile_data"));
ADD_SIGNAL(MethodInfo("settings_changed"));
BIND_CONSTANT( INVALID_CELL );
BIND_CONSTANT( MODE_SQUARE );
BIND_CONSTANT( MODE_ISOMETRIC );
BIND_CONSTANT( MODE_CUSTOM );
BIND_CONSTANT( HALF_OFFSET_X );
BIND_CONSTANT( HALF_OFFSET_Y );
BIND_CONSTANT( HALF_OFFSET_DISABLED );
}
TileMap::TileMap() {
@ -678,12 +858,14 @@ TileMap::TileMap() {
pending_update=false;
quadrant_order_dirty=false;
quadrant_size=16;
cell_size=64;
cell_size=Size2(64,64);
center_x=false;
center_y=false;
collision_layer=1;
friction=1;
bounce=0;
mode=MODE_SQUARE;
half_offset=HALF_OFFSET_DISABLED;
fp_adjust=0.01;
fp_adjust=0.01;

View File

@ -37,12 +37,30 @@
class TileMap : public Node2D {
OBJ_TYPE( TileMap, Node2D );
public:
enum Mode {
MODE_SQUARE,
MODE_ISOMETRIC,
MODE_CUSTOM
};
enum HalfOffset {
HALF_OFFSET_X,
HALF_OFFSET_Y,
HALF_OFFSET_DISABLED,
};
private:
Ref<TileSet> tile_set;
int cell_size;
Size2i cell_size;
int quadrant_size;
bool center_x,center_y;
Mode mode;
Matrix32 custom_transform;
HalfOffset half_offset;
union PosKey {
@ -117,6 +135,12 @@ class TileMap : public Node2D {
void _set_tile_data(const DVector<int>& p_data);
DVector<int> _get_tile_data() const;
void _set_old_cell_size(int p_size) { set_cell_size(Size2(p_size,p_size)); }
int _get_old_cell_size() const { return cell_size.x; }
_FORCE_INLINE_ Vector2 _map_to_world(int p_x,int p_y,bool p_ignore_ofs=false) const;
protected:
@ -132,8 +156,8 @@ public:
void set_tileset(const Ref<TileSet>& p_tileset);
Ref<TileSet> get_tileset() const;
void set_cell_size(int p_size);
int get_cell_size() const;
void set_cell_size(Size2 p_size);
Size2 get_cell_size() const;
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
@ -159,10 +183,28 @@ public:
void set_collision_bounce(float p_bounce);
float get_collision_bounce() const;
void set_mode(Mode p_mode);
Mode get_mode() const;
void set_half_offset(HalfOffset p_half_offset);
HalfOffset get_half_offset() const;
void set_custom_transform(const Matrix32& p_xform);
Matrix32 get_custom_transform() const;
Matrix32 get_cell_transform() const;
Vector2 get_cell_draw_offset() const;
Vector2 map_to_world(const Vector2& p_pos, bool p_ignore_ofs=false) const;
Vector2 world_to_map(const Vector2& p_pos) const;
void clear();
TileMap();
~TileMap();
};
VARIANT_ENUM_CAST(TileMap::Mode);
VARIANT_ENUM_CAST(TileMap::HalfOffset);
#endif // TILE_MAP_H

29
scene/2d/y_sort.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "y_sort.h"
void YSort::set_sort_enabled(bool p_enabled) {
sort_enabled=p_enabled;
VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),sort_enabled);
}
bool YSort::is_sort_enabled() const {
return sort_enabled;
}
void YSort::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_sort_enabled","enabled"),&YSort::set_sort_enabled);
ObjectTypeDB::bind_method(_MD("is_sort_enabled"),&YSort::is_sort_enabled);
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"sort/enabled"),_SCS("set_sort_enabled"),_SCS("is_sort_enabled"));
}
YSort::YSort() {
sort_enabled=true;
VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(),true);
}

17
scene/2d/y_sort.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef Y_SORT_H
#define Y_SORT_H
#include "scene/2d/node_2d.h"
class YSort : public Node2D {
OBJ_TYPE(YSort,Node2D);
bool sort_enabled;
static void _bind_methods();
public:
void set_sort_enabled(bool p_enabled);
bool is_sort_enabled() const;
YSort();
};
#endif // Y_SORT_H

View File

@ -255,16 +255,6 @@ bool Area::is_monitoring_enabled() const {
}
void Area::set_ray_pickable(bool p_ray_pickable) {
ray_pickable=p_ray_pickable;
PhysicsServer::get_singleton()->area_set_ray_pickable(get_rid(),p_ray_pickable);
}
bool Area::is_ray_pickable() const {
return ray_pickable;
}
void Area::_bind_methods() {
@ -289,8 +279,6 @@ void Area::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_priority","priority"),&Area::set_priority);
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_priority);
ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&Area::set_ray_pickable);
ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&Area::is_ray_pickable);
ObjectTypeDB::bind_method(_MD("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled);
@ -310,7 +298,6 @@ void Area::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"density",PROPERTY_HINT_RANGE,"0,1024,0.001"),_SCS("set_density"),_SCS("get_density"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"priority",PROPERTY_HINT_RANGE,"0,128,1"),_SCS("set_priority"),_SCS("get_priority"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"monitoring"),_SCS("set_enable_monitoring"),_SCS("is_monitoring_enabled"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
}
@ -323,7 +310,7 @@ Area::Area() : CollisionObject(PhysicsServer::get_singleton()->area_create(),tru
density=0.1;
priority=0;
monitoring=false;
ray_pickable=false;
set_ray_pickable(false);
set_enable_monitoring(true);
}

View File

@ -52,7 +52,7 @@ private:
real_t density;
int priority;
bool monitoring;
bool ray_pickable;
void _body_inout(int p_status,const RID& p_body, int p_instance, int p_body_shape,int p_area_shape);
@ -109,9 +109,6 @@ public:
void set_priority(real_t p_priority);
real_t get_priority() const;
void set_ray_pickable(bool p_ray_pickable);
bool is_ray_pickable() const;
void set_enable_monitoring(bool p_enable);
bool is_monitoring_enabled() const;

View File

@ -262,7 +262,7 @@ void Camera::_notification(int p_what) {
Transform Camera::get_camera_transform() const {
return get_global_transform();
return get_global_transform().orthonormalized();
}
void Camera::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
@ -695,7 +695,7 @@ Vector<Plane> Camera::get_frustum() const {
else
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH);
return cm.get_projection_planes(get_global_transform());
return cm.get_projection_planes(get_camera_transform());
}
@ -704,7 +704,7 @@ Vector<Plane> Camera::get_frustum() const {
void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
Transform lookat;
lookat.origin=get_global_transform().origin;
lookat.origin=get_camera_transform().origin;
lookat=lookat.looking_at(p_target,p_up_normal);
set_global_transform(lookat);
}

View File

@ -53,8 +53,9 @@ void CollisionObject::_notification(int p_what) {
} else
PhysicsServer::get_singleton()->body_set_space(rid,space);
_update_pickable();
//get space
}
};
case NOTIFICATION_TRANSFORM_CHANGED: {
@ -63,6 +64,11 @@ void CollisionObject::_notification(int p_what) {
else
PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
} break;
case NOTIFICATION_EXIT_WORLD: {
@ -166,12 +172,12 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
}
void CollisionObject::_input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
void CollisionObject::_input_event(Node *p_camera, const InputEvent& p_input_event, const Vector3& p_pos, const Vector3& p_normal, int p_shape) {
if (get_script_instance()) {
get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_input_event,p_pos,p_normal,p_shape);
get_script_instance()->call(SceneStringNames::get_singleton()->_input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
}
emit_signal(SceneStringNames::get_singleton()->input_event,p_input_event,p_pos,p_normal,p_shape);
emit_signal(SceneStringNames::get_singleton()->input_event,p_camera,p_input_event,p_pos,p_normal,p_shape);
}
void CollisionObject::_mouse_enter() {
@ -192,6 +198,28 @@ void CollisionObject::_mouse_exit() {
}
void CollisionObject::_update_pickable() {
if (!is_inside_scene())
return;
bool pickable = ray_pickable && is_inside_scene() && is_visible();
if (area)
PhysicsServer::get_singleton()->area_set_ray_pickable(rid,pickable);
else
PhysicsServer::get_singleton()->body_set_ray_pickable(rid,pickable);
}
void CollisionObject::set_ray_pickable(bool p_ray_pickable) {
ray_pickable=p_ray_pickable;
_update_pickable();
}
bool CollisionObject::is_ray_pickable() const {
return ray_pickable;
}
void CollisionObject::_bind_methods() {
@ -206,15 +234,18 @@ void CollisionObject::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes);
ObjectTypeDB::bind_method(_MD("set_ray_pickable","ray_pickable"),&CollisionObject::set_ray_pickable);
ObjectTypeDB::bind_method(_MD("is_ray_pickable"),&CollisionObject::is_ray_pickable);
ObjectTypeDB::bind_method(_MD("set_capture_input_on_drag","enable"),&CollisionObject::set_capture_input_on_drag);
ObjectTypeDB::bind_method(_MD("get_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid);
BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
BIND_VMETHOD( MethodInfo("_input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("input_event",PropertyInfo(Variant::OBJECT,"camera"),PropertyInfo(Variant::INPUT_EVENT,"event"),PropertyInfo(Variant::VECTOR3,"click_pos"),PropertyInfo(Variant::VECTOR3,"click_normal"),PropertyInfo(Variant::INT,"shape_idx")));
ADD_SIGNAL( MethodInfo("mouse_enter"));
ADD_SIGNAL( MethodInfo("mouse_exit"));
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"input/ray_pickable"),_SCS("set_ray_pickable"),_SCS("is_ray_pickable"));
ADD_PROPERTY(PropertyInfo(Variant::BOOL,"input/capture_on_drag"),_SCS("set_capture_input_on_drag"),_SCS("get_capture_input_on_drag"));
}
@ -296,6 +327,8 @@ CollisionObject::CollisionObject(RID p_rid, bool p_area) {
rid=p_rid;
area=p_area;
capture_input_on_drag=false;
ray_pickable=true;
if (p_area) {
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
} else {
@ -321,6 +354,7 @@ CollisionObject::CollisionObject() {
capture_input_on_drag=false;
ray_pickable=true;
//owner=

View File

@ -51,9 +51,10 @@ class CollisionObject : public Spatial {
};
bool capture_input_on_drag;
bool ray_pickable;
Vector<ShapeData> shapes;
void _update_pickable();
void _update_shapes();
friend class CollisionShape;
@ -69,7 +70,7 @@ protected:
void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods();
friend class Viewport;
virtual void _input_event(const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
virtual void _input_event(Node* p_camera,const InputEvent& p_input_event,const Vector3& p_pos, const Vector3& p_normal, int p_shape);
virtual void _mouse_enter();
virtual void _mouse_exit();
@ -87,9 +88,13 @@ public:
void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
bool is_shape_set_as_trigger(int p_shape_idx) const;
void set_ray_pickable(bool p_ray_pickable);
bool is_ray_pickable() const;
void set_capture_input_on_drag(bool p_capture);
bool get_capture_input_on_drag() const;
_FORCE_INLINE_ RID get_rid() const { return rid; }
CollisionObject();

View File

@ -622,7 +622,7 @@ void SpotLight::_bind_methods() {
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_angle", PROPERTY_HINT_RANGE, "0.01,89.9,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ANGLE );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ATTENUATION );
ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/spot_attenuation", PROPERTY_HINT_EXP_EASING, "attenuation"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SPOT_ATTENUATION );
}

View File

@ -21,6 +21,7 @@ void Navigation::_navmesh_link(int p_id) {
List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
Polygon &p=P->get();
p.owner=&nm;
Vector<int> poly = nm.navmesh->get_polygon(i);
int plen=poly.size();
@ -145,13 +146,14 @@ void Navigation::_navmesh_unlink(int p_id) {
}
int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform) {
int Navigation::navmesh_create(const Ref<NavigationMesh>& p_mesh, const Transform& p_xform, Object *p_owner) {
int id = last_id++;
NavMesh nm;
nm.linked=false;
nm.navmesh=p_mesh;
nm.xform=p_xform;
nm.owner=p_owner;
navmesh_map[id]=nm;
_navmesh_link(id);
@ -453,6 +455,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
bool use_collision=false;
Vector3 closest_point;
float closest_point_d=1e20;
NavMesh *closest_navmesh=NULL;
for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) {
@ -471,10 +474,12 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
closest_point=inters;
use_collision=true;
closest_point_d=p_from.distance_to(inters);
closest_navmesh=p.owner;
} else if (closest_point_d > inters.distance_to(p_from)){
closest_point=inters;
closest_point_d=p_from.distance_to(inters);
closest_navmesh=p.owner;
}
}
}
@ -492,6 +497,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
closest_point_d=d;
closest_point=b;
closest_navmesh=p.owner;
}
}
@ -499,6 +505,10 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
}
}
if (closest_navmesh && closest_navmesh->owner) {
//print_line("navmesh is: "+closest_navmesh->owner->cast_to<Node>()->get_name());
}
return closest_point;
}
@ -577,7 +587,7 @@ Vector3 Navigation::get_up_vector() const{
void Navigation::_bind_methods() {
ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform"),&Navigation::navmesh_create);
ObjectTypeDB::bind_method(_MD("navmesh_create","mesh:NavigationMesh","xform","owner"),&Navigation::navmesh_create,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("navmesh_set_transform","id","xform"),&Navigation::navmesh_set_transform);
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);

View File

@ -41,6 +41,8 @@ class Navigation : public Spatial {
};
struct NavMesh;
struct Polygon {
@ -57,6 +59,8 @@ class Navigation : public Spatial {
float distance;
int prev_edge;
NavMesh *owner;
};
@ -74,6 +78,7 @@ class Navigation : public Spatial {
struct NavMesh {
Object *owner;
Transform xform;
bool linked;
Ref<NavigationMesh> navmesh;
@ -124,7 +129,7 @@ public:
Vector3 get_up_vector() const;
//API should be as dynamic as possible
int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform);
int navmesh_create(const Ref<NavigationMesh>& p_mesh,const Transform& p_xform,Object* p_owner=NULL);
void navmesh_set_transform(int p_id, const Transform& p_xform);
void navmesh_remove(int p_id);

View File

@ -129,7 +129,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) {
if (navmesh.is_valid()) {
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
}
@ -162,7 +162,7 @@ void NavigationMeshInstance::_notification(int p_what) {
if (enabled && navmesh.is_valid()) {
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
break;
}
@ -205,7 +205,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_na
navmesh=p_navmesh;
if (navigation && navmesh.is_valid() && enabled) {
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation));
nav_id = navigation->navmesh_create(navmesh,get_relative_transform(navigation),this);
}
update_gizmo();

View File

@ -66,6 +66,9 @@ void Joint::_update_joint(bool p_only_free) {
joint = _configure_joint(body_a,body_b);
if (joint.is_valid())
PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
if (body_b && joint.is_valid()) {
ba=body_a->get_rid();
@ -107,6 +110,20 @@ NodePath Joint::get_node_b() const{
}
void Joint::set_solver_priority(int p_priority) {
solver_priority=p_priority;
if (joint.is_valid())
PhysicsServer::get_singleton()->joint_set_solver_priority(joint,solver_priority);
}
int Joint::get_solver_priority() const {
return solver_priority;
}
void Joint::_notification(int p_what) {
switch(p_what) {
@ -117,8 +134,6 @@ void Joint::_notification(int p_what) {
case NOTIFICATION_EXIT_SCENE: {
if (joint.is_valid()) {
_update_joint(true);
PhysicsServer::get_singleton()->free(joint);
joint=RID();
}
@ -138,9 +153,13 @@ void Joint::_bind_methods() {
ObjectTypeDB::bind_method( _MD("set_node_b","node"), &Joint::set_node_b );
ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_node_b );
ObjectTypeDB::bind_method( _MD("set_solver_priority","priority"), &Joint::set_solver_priority );
ObjectTypeDB::bind_method( _MD("get_solver_priority"), &Joint::get_solver_priority );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_a"), _SCS("set_node_a"),_SCS("get_node_a") );
ADD_PROPERTY( PropertyInfo( Variant::NODE_PATH, "nodes/node_b"), _SCS("set_node_b"),_SCS("get_node_b") );
ADD_PROPERTY( PropertyInfo( Variant::INT, "solver/priority",PROPERTY_HINT_RANGE,"1,8,1"), _SCS("set_solver_priority"),_SCS("get_solver_priority") );
}
@ -148,7 +167,7 @@ void Joint::_bind_methods() {
Joint::Joint() {
solver_priority=1;
}

View File

@ -44,6 +44,8 @@ class Joint : public Spatial {
NodePath a;
NodePath b;
int solver_priority;
protected:
@ -62,6 +64,9 @@ public:
void set_node_b(const NodePath& p_node_b);
NodePath get_node_b() const;
void set_solver_priority(int p_priority);
int get_solver_priority() const;
RID get_joint() const { return joint; }
Joint();

View File

@ -179,7 +179,7 @@ void VehicleWheel::set_damping_compression(float p_value){
}
float VehicleWheel::get_damping_compression() const{
return m_wheelsDampingRelaxation;
return m_wheelsDampingCompression;
}
void VehicleWheel::set_damping_relaxation(float p_value){
@ -745,11 +745,12 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
{
if (engine_force != 0.f)
{
rollingFriction = engine_force* s->get_step();
rollingFriction = -engine_force* s->get_step();
} else
{
real_t defaultRollingFrictionImpulse = 0.f;
real_t maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
float cbrake = MAX(wheelInfo.m_brake,brake);
real_t maxImpulse = cbrake ? cbrake : defaultRollingFrictionImpulse;
btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
rollingFriction = _calc_rolling_friction(contactPt);
}
@ -1009,9 +1010,9 @@ void VehicleBody::_bind_methods(){
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed);
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"0.01,1024.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/engine_force",PROPERTY_HINT_RANGE,"0.00,1024.0,0.01"),_SCS("set_engine_force"),_SCS("get_engine_force"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/brake",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_brake"),_SCS("get_brake"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"motion/steering",PROPERTY_HINT_RANGE,"-180,180.0,0.01"),_SCS("set_steering"),_SCS("get_steering"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/mass",PROPERTY_HINT_RANGE,"0.01,65536,0.01"),_SCS("set_mass"),_SCS("get_mass"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"body/friction",PROPERTY_HINT_RANGE,"0.01,1,0.01"),_SCS("set_friction"),_SCS("get_friction"));

View File

@ -180,6 +180,10 @@ void AnimationPlayer::_get_property_list( List<PropertyInfo> *p_list) const {
}
void AnimationPlayer::advance(float p_time) {
_animation_process( p_time );
}
void AnimationPlayer::_notification(int p_what) {
@ -1227,6 +1231,8 @@ void AnimationPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("get_current_animation_pos"),&AnimationPlayer::get_current_animation_pos);
ObjectTypeDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length);
ObjectTypeDB::bind_method(_MD("advance","delta"),&AnimationPlayer::advance);
ADD_PROPERTY( PropertyInfo( Variant::INT, "playback/process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), _SCS("set_animation_process_mode"), _SCS("get_animation_process_mode"));
ADD_PROPERTY( PropertyInfo( Variant::REAL, "playback/default_blend_time", PROPERTY_HINT_RANGE, "0,4096,0.01"), _SCS("set_default_blend_time"), _SCS("get_default_blend_time"));

View File

@ -283,6 +283,8 @@ public:
float get_current_animation_pos() const;
float get_current_animation_length() const;
void advance(float p_time);
void set_root(const NodePath& p_root);
NodePath get_root() const;

View File

@ -280,8 +280,8 @@ float EventPlayer::get_channel_last_note_time(int p_channel) const {
void EventPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&EventPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&EventPlayer::get_stream);
ObjectTypeDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream);
ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play);
ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop);

View File

@ -67,6 +67,9 @@ Array ButtonGroup::_get_button_list() const {
List<BaseButton*> b;
get_button_list(&b);
b.sort_custom<Node::Comparator>();
Array arr;
arr.resize(b.size());

View File

@ -397,6 +397,7 @@ void Label::regenerate_word_cache() {
}
if (current=='\n') {
insert_newline=true;
} else {
@ -446,7 +447,7 @@ void Label::regenerate_word_cache() {
}
total_char_cache -= line_count + 1; // do not count new lines (including the first one)
//total_char_cache -= line_count + 1; // do not count new lines (including the first one)
if (!autowrap) {

View File

@ -164,6 +164,9 @@ void Viewport::_parent_visibility_changed() {
Control *c = parent->cast_to<Control>();
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible());
_update_listener();
_update_listener_2d();
}
@ -394,7 +397,7 @@ void Viewport::_notification(int p_what) {
if (obj) {
CollisionObject *co = obj->cast_to<CollisionObject>();
if (co) {
co->_input_event(ev,Vector3(),Vector3(),0);
co->_input_event(camera,ev,Vector3(),Vector3(),0);
captured=true;
if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) {
physics_object_capture=0;
@ -416,7 +419,7 @@ void Viewport::_notification(int p_what) {
if (last_id) {
if (ObjectDB::get_instance(last_id)) {
//good, exists
last_object->_input_event(ev,result.position,result.normal,result.shape);
last_object->_input_event(camera,ev,result.position,result.normal,result.shape);
if (last_object->get_capture_input_on_drag() && ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && ev.mouse_button.pressed) {
physics_object_capture=last_id;
}
@ -440,10 +443,13 @@ void Viewport::_notification(int p_what) {
bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
ObjectID new_collider=0;
if (col) {
if (result.collider) {
CollisionObject *co = result.collider->cast_to<CollisionObject>();
if (co) {
co->_input_event(ev,result.position,result.normal,result.shape);
co->_input_event(camera,ev,result.position,result.normal,result.shape);
last_object=co;
last_id=result.collider_id;
new_collider=last_id;
@ -541,7 +547,7 @@ Rect2 Viewport::get_rect() const {
void Viewport::_update_listener() {
if (is_inside_scene() && audio_listener && camera) {
if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible()))) {
SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space());
} else {
SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
@ -552,7 +558,7 @@ void Viewport::_update_listener() {
void Viewport::_update_listener_2d() {
if (is_inside_scene() && audio_listener_2d)
if (is_inside_scene() && audio_listener && camera && (!get_parent() || (get_parent()->cast_to<Control>() && get_parent()->cast_to<Control>()->is_visible())))
SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space());
else
SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID());

View File

@ -100,6 +100,7 @@
#include "scene/2d/sample_player_2d.h"
#include "scene/2d/screen_button.h"
#include "scene/2d/remote_transform_2d.h"
#include "scene/2d/y_sort.h"
#include "scene/2d/position_2d.h"
#include "scene/2d/tile_map.h"
@ -491,6 +492,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier2D>();
ObjectTypeDB::register_type<VisibilityEnabler2D>();
ObjectTypeDB::register_type<Polygon2D>();
ObjectTypeDB::register_type<YSort>();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
ObjectTypeDB::set_type_enabled("CollisionPolygon2D",false);

View File

@ -1716,7 +1716,7 @@ void Animation::clear() {
}
void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err) {
void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,float p_alowed_angular_err,float p_max_optimizable_angle) {
ERR_FAIL_INDEX(p_idx,tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM);
@ -1779,6 +1779,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
} else {
Quat r02 = (q0.inverse() * q2).normalized();
Quat r01 = (q0.inverse() * q1).normalized();
@ -1788,6 +1789,9 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
r02.get_axis_and_angle(v02,a02);
r01.get_axis_and_angle(v01,a01);
if (Math::abs(a02)>p_max_optimizable_angle)
continue;
if (v01.dot(v02)<0) {
//make sure both rotations go the same way to compare
v02=-v02;
@ -1905,7 +1909,7 @@ void Animation::_transform_track_optimize(int p_idx,float p_alowed_linear_err,fl
}
void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err) {
void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err,float p_angle_max) {
int total_tt=0;
@ -1913,7 +1917,7 @@ void Animation::optimize(float p_allowed_linear_err,float p_allowed_angular_err)
for(int i=0;i<tracks.size();i++) {
if (tracks[i]->type==TYPE_TRANSFORM)
_transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err);
_transform_track_optimize(i,p_allowed_linear_err,p_allowed_angular_err,p_angle_max);
}

View File

@ -204,7 +204,7 @@ private:
return idxr;
}
void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01);
void _transform_track_optimize(int p_idx, float p_allowed_err=0.05, float p_alowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
protected:
@ -271,7 +271,7 @@ public:
void clear();
void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01);
void optimize(float p_allowed_linear_err=0.05,float p_allowed_angular_err=0.01,float p_max_optimizable_angle=Math_PI*0.125);
Animation();
~Animation();

View File

@ -225,22 +225,34 @@ Error PackedScene::_parse_node(Node *p_owner,Node *p_node,int p_parent_idx, Map<
p_node->get_property_list(&plist);
for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) {
continue;
}
String name = E->get().name;
Variant value = p_node->get( E->get().name );
if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero())
if (E->get().usage & PROPERTY_USAGE_STORE_IF_NONZERO && value.is_zero()) {
continue;
}
if (nd.instance>=0) {
//only save changed properties in instance
if (!instance_state.has(name))
/*
// this was commented because it would not save properties created from within script
// done with _get_property_list, that are not in the original node.
// if some property is not saved, check again
if (!instance_state.has(name)) {
print_line("skip not in instance");
continue;
if (instance_state[name]==value)
}*/
if (instance_state[name]==value) {
continue;
}
}

View File

@ -67,7 +67,6 @@ void AreaPairSW::solve(float p_step) {
AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape) {
body=p_body;
area=p_area;
body_shape=p_body_shape;
@ -75,6 +74,8 @@ AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_are
colliding=false;
body->add_constraint(this,0);
area->add_constraint(this);
if (p_body->get_mode()==PhysicsServer::BODY_MODE_KINEMATIC)
p_body->set_active(true);
}

View File

@ -148,8 +148,6 @@ void AreaSW::call_queries() {
return;
}
for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) {
if (E->get().state==0)
@ -182,8 +180,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move
point_attenuation=1;
density=0.1;
priority=0;
ray_pickable=false;
set_ray_pickable(false);
monitor_callback_id=0;
}

View File

@ -48,7 +48,6 @@ class AreaSW : public CollisionObjectSW{
float point_attenuation;
float density;
int priority;
bool ray_pickable;
ObjectID monitor_callback_id;
StringName monitor_callback_method;
@ -139,8 +138,6 @@ public:
_FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; }
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }

View File

@ -217,4 +217,5 @@ CollisionObjectSW::CollisionObjectSW(Type p_type) {
space=NULL;
instance_id=0;
layer_mask=1;
ray_pickable=true;
}

View File

@ -94,6 +94,9 @@ protected:
virtual void _shapes_changed()=0;
void _set_space(SpaceSW *space);
bool ray_pickable;
CollisionObjectSW(Type p_type);
public:
@ -119,6 +122,9 @@ public:
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ SpaceSW* get_space() const { return space; }
_FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable=p_enable; }
_FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; }
_FORCE_INLINE_ void set_layer_mask(uint32_t p_mask) { layer_mask=p_mask; }
_FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; }

View File

@ -38,12 +38,13 @@ class ConstraintSW {
uint64_t island_step;
ConstraintSW *island_next;
ConstraintSW *island_list_next;
int priority;
RID self;
protected:
ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; }
ConstraintSW(BodySW **p_body_ptr=NULL,int p_body_count=0) { _body_ptr=p_body_ptr; _body_count=p_body_count; island_step=0; priority=1; }
public:
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
@ -62,6 +63,9 @@ public:
_FORCE_INLINE_ BodySW **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
virtual bool setup(float p_step)=0;
virtual void solve(float p_step)=0;

View File

@ -836,6 +836,22 @@ void PhysicsServerSW::body_set_force_integration_callback(RID p_body,Object *p_r
}
void PhysicsServerSW::body_set_ray_pickable(RID p_body,bool p_enable) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
body->set_ray_pickable(p_enable);
}
bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const{
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,false);
return body->is_ray_pickable();
}
/* JOINT API */
@ -1000,6 +1016,21 @@ bool PhysicsServerSW::hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) co
return hinge_joint->get_flag(p_flag);
}
void PhysicsServerSW::joint_set_solver_priority(RID p_joint,int p_priority) {
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
joint->set_priority(p_priority);
}
int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
return joint->get_priority();
}
PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const {
JointSW *joint = joint_owner.get(p_joint);

View File

@ -201,6 +201,9 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
virtual void body_set_ray_pickable(RID p_body,bool p_enable);
virtual bool body_is_ray_pickable(RID p_body) const;
/* JOINT API */
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B);
@ -244,6 +247,9 @@ public:
virtual JointType joint_get_type(RID p_joint) const;
virtual void joint_set_solver_priority(RID p_joint,int p_priority);
virtual int joint_get_solver_priority(RID p_joint) const;
#if 0
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value);
virtual real_t joint_get_param(RID p_joint,JointParam p_param) const;

View File

@ -71,12 +71,13 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
real_t min_d=1e10;
for(int i=0;i<amount;i++) {
if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
continue;
if (space->intersection_query_results[i]->get_type()==CollisionObjectSW::TYPE_AREA && !(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
if (!(static_cast<AreaSW*>(space->intersection_query_results[i])->is_ray_pickable()))
continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self()))
@ -97,6 +98,8 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
if (shape->intersect_segment(local_from,local_to,shape_point,shape_normal)) {
Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);

View File

@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "step_sw.h"
#include "joints_sw.h"
void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) {
@ -68,6 +68,10 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
int at_priority=1;
while(p_island) {
for(int i=0;i<p_iterations;i++) {
ConstraintSW *ci=p_island;
@ -76,6 +80,29 @@ void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta
ci=ci->get_island_next();
}
}
at_priority++;
{
ConstraintSW *ci=p_island;
ConstraintSW *prev=NULL;
while(ci) {
if (ci->get_priority()<at_priority) {
if (prev) {
prev->set_island_next(ci->get_island_next()); //remove
} else {
p_island=ci->get_island_next();
}
} else {
prev=ci;
}
ci=ci->get_island_next();
}
}
}
}
void StepSW::_check_suspend(BodySW *p_island,float p_delta) {

View File

@ -180,6 +180,7 @@ Area2DSW::Area2DSW() : CollisionObject2DSW(TYPE_AREA), monitor_query_list(this),
gravity_vector=Vector2(0,-1);
gravity_is_point=false;
point_attenuation=1;
density=0.1;
priority=0;
monitor_callback_id=0;

View File

@ -75,6 +75,8 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,i
colliding=false;
body->add_constraint(this,0);
area->add_constraint(this);
if (p_body->get_mode()==Physics2DServer::BODY_MODE_KINEMATIC) //need to be active to process pair
p_body->set_active(true);
}

View File

@ -520,6 +520,9 @@ void PhysicsServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
/* JOINT API */
BIND_CONSTANT( JOINT_PIN );
@ -627,6 +630,9 @@ void PhysicsServer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);

View File

@ -450,6 +450,10 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
virtual void body_set_ray_pickable(RID p_body,bool p_enable)=0;
virtual bool body_is_ray_pickable(RID p_body) const=0;
/* JOINT API */
enum JointType {
@ -464,6 +468,8 @@ public:
virtual JointType joint_get_type(RID p_joint) const=0;
virtual void joint_set_solver_priority(RID p_joint,int p_priority)=0;
virtual int joint_get_solver_priority(RID p_joint) const=0;
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B)=0;

View File

@ -57,6 +57,7 @@ void register_server_types() {
ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>();
ObjectTypeDB::register_type<Physics2DShapeQueryParameters>();
ObjectTypeDB::register_type<PhysicsShapeQueryParameters>();
ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>();
ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>();
ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>();

View File

@ -879,10 +879,13 @@ void SpatialSoundServerSW::update(float p_delta) {
float volume_attenuation = 0.0;
float air_absorption_hf_cutoff = 0.0;
float air_absorption = 0.0;
float pitch_scale=0.0;
float pitch_scale=1.0;
Vector3 panning;
//print_line("listeners: "+itos(space->listeners.size()));
for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
Listener *listener=listener_owner.get(L->get());
@ -899,9 +902,11 @@ void SpatialSoundServerSW::update(float p_delta) {
float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
float attenuation=1;
//print_line("DIST MIN: "+rtos(distance_min));
//print_line("DIST MAX: "+rtos(distance_max));
if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max);
attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
}
float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
@ -945,7 +950,7 @@ void SpatialSoundServerSW::update(float p_delta) {
air_absorption+=weight*absorption;
air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
panning+=vpanning*weight;
pitch_scale+=pscale*weight;
//pitch_scale+=pscale*weight;
}
@ -991,8 +996,8 @@ void SpatialSoundServerSW::update(float p_delta) {
reverb_send*=volume_scale;
int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE];
if (mix_rate<=0) {
if (mix_rate<=0) {
ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
to_disable.push_back(ActiveVoice(source,voice)); // oh well..
continue; //invalid mix rate, disabling

View File

@ -904,7 +904,7 @@ void SpatialSound2DServerSW::update(float p_delta) {
if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max);
attenuation = Math::pow(1.0 - ((distance - distance_min)/distance_max),CLAMP(attenuation_exp,0.001,16));
attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
}
float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];

View File

@ -1202,7 +1202,7 @@ RID VisualServerRaster::camera_create() {
}
void VisualServerRaster::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) {
VS_CHANGED;
VS_CHANGED
Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!camera);
camera->type=Camera::PERSPECTIVE;
@ -1226,7 +1226,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr
VS_CHANGED;
Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!camera);
camera->transform=p_transform;
camera->transform=p_transform.orthonormalized();
}
@ -3531,6 +3531,15 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen
canvas_item->commands.push_back(bm);
};
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
canvas_item->sort_y=p_enable;
}
void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
VS_CHANGED;
@ -5591,26 +5600,30 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
float opacity = ci->opacity * p_opacity;
#ifndef ONTOP_DISABLED
CanvasItem **child_items = ci->child_items.ptr();
int child_item_count=ci->child_items.size();
int top_item_count=0;
CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*));
if (ci->clip) {
rasterizer->canvas_set_clip(true,global_rect);
canvas_clip=global_rect;
}
if (ci->sort_y) {
SortArray<CanvasItem*,CanvasItemPtrSort> sorter;
sorter.sort(child_items,child_item_count);
}
for(int i=0;i<child_item_count;i++) {
if (child_items[i]->ontop)
top_items[top_item_count++]=child_items[i];
else {
continue;
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
}
#endif
if (s!=0) {
@ -5746,20 +5759,13 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
rasterizer->canvas_set_clip(true,canvas_clip);
}
#ifndef ONTOP_DISABLED
for(int i=0;i<child_item_count;i++) {
for(int i=0;i<top_item_count;i++) {
_render_canvas_item(top_items[i],xform,p_clip_rect,opacity);
if (!child_items[i]->ontop)
continue;
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
#else
for(int i=0;i<p_canvas_item->child_items.size();i++) {
_render_canvas_item(p_canvas_item->child_items[i],xform,p_clip_rect,opacity);
}
#endif
if (ci->clip) {
rasterizer->canvas_set_clip(false,Rect2());

View File

@ -446,6 +446,7 @@ class VisualServerRaster : public VisualServer {
bool clip;
bool visible;
bool ontop;
bool sort_y;
float opacity;
float self_opacity;
MaterialBlendMode blend_mode;
@ -460,11 +461,18 @@ class VisualServerRaster : public VisualServer {
const Rect2& get_rect() const;
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true;};
CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; }
CanvasItem() { clip=false; E=NULL; opacity=1; self_opacity=1; blend_mode=MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; sort_y=false;}
~CanvasItem() { clear(); }
};
struct CanvasItemPtrSort {
_FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const {
return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
}
};
struct Canvas {
@ -1135,6 +1143,7 @@ public:
virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform);
virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend);
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
virtual void canvas_item_clear(RID p_item);
virtual void canvas_item_raise(RID p_item);

View File

@ -1107,6 +1107,8 @@ public:
FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode );
FUNC2(canvas_item_add_clip_ignore,RID, bool );
FUNC2(canvas_item_set_sort_children_by_y,RID,bool);
FUNC1(canvas_item_clear,RID);
FUNC1(canvas_item_raise,RID);

View File

@ -944,6 +944,7 @@ public:
virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0;
virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0;
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0;
virtual void canvas_item_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;

View File

@ -2144,6 +2144,7 @@ void Collada::_parse_scene(XMLParser& parser) {
if (name=="instance_visual_scene") {
state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url"));
print_line("***ROOT VISUAL SCENE: "+state.root_visual_scene);
} if (name=="instance_physics_scene") {
state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url"));
@ -2513,6 +2514,9 @@ bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene,Node *p_node,Lis
ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
ERR_FAIL_COND_V(!nj,false);
if (!nj->owner) {
print_line("Has no owner: "+nj->name);
}
ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
NodeSkeleton *sk = nj->owner;

View File

@ -92,6 +92,7 @@ public:
String gradient_image;
bool disable_filter;
bool round_advance;
@ -153,6 +154,8 @@ public:
color_use_monochrome=p_value;
else if (n=="advanced/round_advance")
round_advance=p_value;
else if (n=="advanced/disable_filter")
disable_filter=p_value;
else
return false;
@ -217,6 +220,8 @@ public:
r_ret=color_use_monochrome;
else if (n=="advanced/round_advance")
r_ret=round_advance;
else if (n=="advanced/disable_filter")
r_ret=disable_filter;
else
return false;
@ -265,6 +270,7 @@ public:
}
p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome"));
p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/round_advance"));
p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/disable_filter"));
}
@ -302,6 +308,7 @@ public:
color_use_monochrome=false;
round_advance=true;
disable_filter=false;
}
@ -331,6 +338,7 @@ public:
color_use_monochrome=false;
round_advance=true;
disable_filter=false;
}
@ -1260,6 +1268,7 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
int space_space = from->get_option("extra_space/space");
int top_space = from->get_option("extra_space/top");
int bottom_space = from->get_option("extra_space/bottom");
bool disable_filter = from->get_option("advanced/disable_filter");
Ref<Font> font;
@ -1279,7 +1288,12 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
//register texures
{
Ref<ImageTexture> t = memnew(ImageTexture);
t->create_from_image(atlas);
int flags;
if (disable_filter)
flags=0;
else
flags=Texture::FLAG_FILTER;
t->create_from_image(atlas,flags);
t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
font->add_texture(t);

View File

@ -1829,9 +1829,9 @@ void ColladaImport::create_animation(int p_clip, bool p_make_tracks_in_all_bones
if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
anim_length=collada.state.animation_clips[p_clip].end;
while(f<collada.state.animation_length) {
if (f>=collada.state.animation_length)
f=collada.state.animation_length;
while(f<anim_length) {
if (f>=anim_length)
f=anim_length;
base_snapshots.push_back(f);
f+=snapshot_interval;

View File

@ -40,6 +40,7 @@
#include "scene/3d/body_shape.h"
#include "scene/3d/physics_body.h"
#include "scene/3d/portal.h"
#include "scene/3d/vehicle_body.h"
#include "os/os.h"
@ -649,9 +650,10 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_BILLBOARDS,"Create","Create Billboards (-bb)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create","Create Impostors (-imp:dist)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_LODS,"Create","Create LODs (-lod:dist)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Cars (-car)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Car Wheels (-wheel)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Vehicles (-vehicle)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Vehicle Wheels (-wheel)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_NAVMESH,"Create","Create Navigation Meshes (-navmesh)",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_LIGHTMAP_LAYER,"Create","Detect LightMap Layer (-lm:<int>).",true},
{-1,NULL,NULL,false}
};
@ -1199,6 +1201,17 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
}
}
}
if (p_flags&SCENE_FLAG_DETECT_LIGHTMAP_LAYER && _teststr(name,"lm") && p_node->cast_to<MeshInstance>()) {
MeshInstance *mi = p_node->cast_to<MeshInstance>();
String str=name;
int layer = str.substr(str.find("lm")+3,str.length()).to_int();
mi->set_baked_light_texture_id(layer);
}
if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {
if (isroot)
@ -1262,6 +1275,46 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
p_node->replace_by(nmi);
memdelete(p_node);
p_node=nmi;
} else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"vehicle")) {
if (isroot)
return p_node;
Node *owner = p_node->get_owner();
Spatial *s = p_node->cast_to<Spatial>();
VehicleBody *bv = memnew( VehicleBody );
String n = _fixstr(p_node->get_name(),"vehicle");
bv->set_name(n);
p_node->replace_by(bv);
p_node->set_name(n);
bv->add_child(p_node);
bv->set_owner(owner);
p_node->set_owner(owner);
bv->set_transform(s->get_transform());
s->set_transform(Transform());
p_node=bv;
} else if (p_flags&SCENE_FLAG_CREATE_CARS &&_teststr(name,"wheel")) {
if (isroot)
return p_node;
Node *owner = p_node->get_owner();
Spatial *s = p_node->cast_to<Spatial>();
VehicleWheel *bv = memnew( VehicleWheel );
String n = _fixstr(p_node->get_name(),"wheel");
bv->set_name(n);
p_node->replace_by(bv);
p_node->set_name(n);
bv->add_child(p_node);
bv->set_owner(owner);
p_node->set_owner(owner);
bv->set_transform(s->get_transform());
s->set_transform(Transform());
p_node=bv;
} else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) {

View File

@ -125,6 +125,7 @@ public:
SCENE_FLAG_DETECT_ALPHA=1<<15,
SCENE_FLAG_DETECT_VCOLOR=1<<16,
SCENE_FLAG_CREATE_NAVMESH=1<<17,
SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
SCENE_FLAG_REMOVE_NOIMP=1<<24,
SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,

View File

@ -64,6 +64,8 @@ void SamplePlayerEditor::_play() {
return;
node->call("play",samples->get_item_text( samples->get_selected() ));
stop->set_pressed(false);
play->set_pressed(true);
}
void SamplePlayerEditor::_stop() {
@ -74,6 +76,9 @@ void SamplePlayerEditor::_stop() {
return;
node->call("stop_all");
print_line("STOP ALL!!");
stop->set_pressed(true);
play->set_pressed(false);
}

View File

@ -1925,6 +1925,15 @@ void SpatialEditorViewport::_menu_option(int p_option) {
call_deferred("update_transform_gizmo_view");
} break;
case VIEW_AUDIO_LISTENER: {
int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
bool current = view_menu->get_popup()->is_item_checked( idx );
current=!current;
viewport->set_as_audio_listener(current);
view_menu->get_popup()->set_item_checked( idx, current );
} break;
}
@ -2055,6 +2064,13 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) {
_menu_option(VIEW_PERSPECTIVE);
if (env != camera->get_environment().is_valid())
_menu_option(VIEW_ENVIRONMENT);
if (p_state.has("listener")) {
bool listener = p_state["listener"];
int idx = view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER);
viewport->set_as_audio_listener(listener);
view_menu->get_popup()->set_item_checked( idx, listener );
}
}
@ -2068,6 +2084,7 @@ Dictionary SpatialEditorViewport::get_state() const {
d["distance"]=cursor.distance;
d["use_environment"]=camera->get_environment().is_valid();
d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
d["listener"]=viewport->is_audio_listener();
return d;
}
@ -2147,6 +2164,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT);
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(VIEW_ENVIRONMENT),true);
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_item("Audio Listener",VIEW_AUDIO_LISTENER);
view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_item("Selection (F)",VIEW_CENTER_TO_SELECTION);
view_menu->get_popup()->add_item("Align with view (Ctrl+Shift+F)",VIEW_ALIGN_SELECTION_WITH_VIEW);
@ -2163,6 +2183,12 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
previewing=NULL;
preview=NULL;
gizmo_scale=1.0;
if (p_index==0) {
view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(VIEW_AUDIO_LISTENER),true);
viewport->set_as_audio_listener(true);
}
EditorSettings::get_singleton()->connect("settings_changed",this,"update_transform_gizmo_view");
}
@ -3307,6 +3333,11 @@ void SpatialEditor::clear() {
}
}
for(int i=0;i<4;i++) {
viewports[i]->view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(SpatialEditorViewport::VIEW_AUDIO_LISTENER),i==0);
viewports[i]->viewport->set_as_audio_listener(i==0);
}
view_menu->get_popup()->set_item_checked( view_menu->get_popup()->get_item_index(MENU_VIEW_GRID), true );

View File

@ -65,7 +65,7 @@ public:
class SpatialEditorViewport : public Control {
OBJ_TYPE( SpatialEditorViewport, Control );
friend class SpatialEditor;
enum {
VIEW_TOP,
@ -78,7 +78,8 @@ class SpatialEditorViewport : public Control {
VIEW_ALIGN_SELECTION_WITH_VIEW,
VIEW_PERSPECTIVE,
VIEW_ENVIRONMENT,
VIEW_ORTHOGONAL
VIEW_ORTHOGONAL,
VIEW_AUDIO_LISTENER,
};
enum {
GIZMO_BASE_LAYER=25

View File

@ -166,7 +166,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse();
Vector2 snap = Vector2(1,1)*node->get_cell_size();
Vector2 snap = node->get_cell_size();
switch(p_event.type) {
@ -218,7 +218,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
if (mb.mod.shift) {
tool=TOOL_SELECTING;
selection_begin =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
selection_begin =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
selection.pos=selection_begin;
selection.size=Point2(0,0);
selection_active=true;
@ -229,7 +229,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
int id = get_selected_tile();
if (id!=TileMap::INVALID_CELL) {
tool=TOOL_PAINTING;
Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
Point2i local =node->world_to_map((xform_inv.xform(Point2(mb.x,mb.y))));
paint_undo.clear();
CellOp op;
op.idx = node->get_cell(local.x,local.y);
@ -278,7 +278,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
} else if (mb.pressed && tool==TOOL_NONE) {
tool=TOOL_ERASING;
Point2i local =(xform_inv.xform(Point2(mb.x,mb.y))/snap).floor();
Point2i local =node->world_to_map(xform_inv.xform(Point2(mb.x,mb.y)));
paint_undo.clear();
CellOp op;
op.idx = node->get_cell(local.x,local.y);
@ -322,7 +322,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
const InputEventMouseMotion &mm=p_event.mouse_motion;
Point2i new_over_tile = (xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
Point2i new_over_tile = node->world_to_map(xform_inv.xform(Point2(mm.x,mm.y)));//(xform_inv.xform(Point2(mm.x,mm.y))/snap).floor();
if (new_over_tile!=over_tile) {
over_tile=new_over_tile;
@ -469,44 +469,104 @@ void TileMapEditor::_canvas_draw() {
if (!node)
return;
int cell_size=node->get_cell_size();
Size2 cell_size=node->get_cell_size();
Matrix32 cell_xf = node->get_cell_transform();
Matrix32 xform = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse();
Size2 screen_size=canvas_item_editor->get_size();
{
Rect2 aabb;
aabb.pos=xform_inv.xform(Vector2());
aabb.expand_to(xform_inv.xform(Vector2(0,screen_size.height)));
aabb.expand_to(xform_inv.xform(Vector2(screen_size.width,0)));
aabb.expand_to(xform_inv.xform(screen_size));
Rect2i si=aabb;
aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
aabb.expand_to(node->world_to_map(xform_inv.xform(screen_size)));
Rect2i si=aabb.grow(1.0);
for(int i=(si.pos.x/cell_size)-1;i<=(si.pos.x+si.size.x)/cell_size;i++) {
if (node->get_half_offset()!=TileMap::HALF_OFFSET_X) {
int ofs = i*cell_size;
for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
Vector2 from = xform.xform(node->map_to_world(Vector2(i,si.pos.y)));
Vector2 to = xform.xform(node->map_to_world(Vector2(i,si.pos.y+si.size.y+1)));
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
canvas_item_editor->draw_line(xform.xform(Point2(ofs,si.pos.y)),xform.xform(Point2(ofs,si.pos.y+si.size.y)),col,1);
canvas_item_editor->draw_line(from,to,col,1);
}
} else {
for(int i=(si.pos.x)-1;i<=(si.pos.x+si.size.x);i++) {
for(int j=(si.pos.y)-1;j<=(si.pos.y+si.size.y);j++) {
Vector2 ofs;
if (ABS(j)&1) {
ofs=cell_xf[0]*0.5;
}
Vector2 from = xform.xform(node->map_to_world(Vector2(i,j),true)+ofs);
Vector2 to = xform.xform(node->map_to_world(Vector2(i,j+1),true)+ofs);
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
canvas_item_editor->draw_line(from,to,col,1);
}
}
}
if (node->get_half_offset()!=TileMap::HALF_OFFSET_Y) {
for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
Vector2 from = xform.xform(node->map_to_world(Vector2(si.pos.x,i)));
Vector2 to = xform.xform(node->map_to_world(Vector2(si.pos.x+si.size.x+1,i)));
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
canvas_item_editor->draw_line(from,to,col,1);
}
} else {
for(int i=(si.pos.y)-1;i<=(si.pos.y+si.size.y);i++) {
for(int j=(si.pos.x)-1;j<=(si.pos.x+si.size.x);j++) {
Vector2 ofs;
if (ABS(j)&1) {
ofs=cell_xf[1]*0.5;
}
Vector2 from = xform.xform(node->map_to_world(Vector2(j,i),true)+ofs);
Vector2 to = xform.xform(node->map_to_world(Vector2(j+1,i),true)+ofs);
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
canvas_item_editor->draw_line(from,to,col,1);
}
}
for(int i=(si.pos.y/cell_size)-1;i<=(si.pos.y+si.size.y)/cell_size;i++) {
int ofs = i*cell_size;
}
/*
for(int i=(si.pos.y/cell_size.y)-1;i<=(si.pos.y+si.size.y)/cell_size.y;i++) {
int ofs = i*cell_size.y;
Color col=i==0?Color(1,0.8,0.2,0.5):Color(1,0.3,0.1,0.2);
canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);
canvas_item_editor->draw_line(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),col,1);*/
}
if (selection_active) {
Vector<Vector2> points;
points.push_back( xform.xform( selection.pos * cell_size) );
points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,0)) * cell_size) );
points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,selection.size.y+1)) * cell_size) );
points.push_back( xform.xform( (selection.pos+Point2(0,selection.size.y+1)) * cell_size) );
points.push_back( xform.xform( node->map_to_world(( selection.pos ) )));
points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,0)) ) ));
points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,selection.size.y+1)) ) ));
points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(0,selection.size.y+1)) ) ));
Color col=Color(0.2,0.8,1,0.4);
canvas_item_editor->draw_colored_polygon(points,col);
@ -515,15 +575,22 @@ void TileMapEditor::_canvas_draw() {
if (mouse_over){
const Vector2 endpoints[4]={
xform.xform( over_tile * cell_size) ,
xform.xform( (over_tile+Point2(1,0)) * cell_size) ,
xform.xform( (over_tile+Point2(1,1)) * cell_size) ,
xform.xform( (over_tile+Point2(0,1)) * cell_size) ,
Vector2 endpoints[4]={
( node->map_to_world(over_tile,true) ) ,
( node->map_to_world((over_tile+Point2(1,0)),true ) ),
( node->map_to_world((over_tile+Point2(1,1)),true ) ),
( node->map_to_world((over_tile+Point2(0,1)),true ) )
};
for(int i=0;i<4;i++) {
if (node->get_half_offset()==TileMap::HALF_OFFSET_X && ABS(over_tile.y)&1)
endpoints[i]+=cell_xf[0]*0.5;
if (node->get_half_offset()==TileMap::HALF_OFFSET_Y && ABS(over_tile.x)&1)
endpoints[i]+=cell_xf[1]*0.5;
endpoints[i]=xform.xform(endpoints[i]);
}
Color col;
if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
col=Color(0.2,0.8,1.0,0.8);
@ -542,10 +609,10 @@ void TileMapEditor::_canvas_draw() {
Vector<Vector2> points;
points.push_back( xform.xform( duplicate.pos * cell_size) );
points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,0)) * cell_size) );
points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1)) * cell_size) );
points.push_back( xform.xform( (duplicate.pos+Point2(0,duplicate.size.y+1)) * cell_size) );
points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1))) ));
points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(0,duplicate.size.y+1))) ));
Color col=Color(0.2,1.0,0.8,0.4);
canvas_item_editor->draw_colored_polygon(points,col);
@ -562,18 +629,19 @@ void TileMapEditor::_canvas_draw() {
Ref<Texture> t = ts->tile_get_texture(st);
if (t.is_valid()) {
Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset());
Rect2 r = ts->tile_get_region(st);
Size2 sc = (endpoints[2]-endpoints[0])/cell_size;
Size2 sc = xform.get_scale();
if (mirror_x->is_pressed())
sc.x*=-1.0;
if (mirror_y->is_pressed())
sc.y*=-1.0;
if (r==Rect2()) {
canvas_item_editor->draw_texture_rect(t,Rect2(endpoints[0],t->get_size()*sc),false,Color(1,1,1,0.5));
canvas_item_editor->draw_texture_rect(t,Rect2(from,t->get_size()*sc),false,Color(1,1,1,0.5));
} else {
canvas_item_editor->draw_texture_rect_region(t,Rect2(endpoints[0],r.get_size()*sc),r,Color(1,1,1,0.5));
canvas_item_editor->draw_texture_rect_region(t,Rect2(from,r.get_size()*sc),r,Color(1,1,1,0.5));
}
}
}

View File

@ -44,6 +44,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
Node *child = scene->get_child(i);
if (!child->cast_to<Sprite>()) {
if (child->get_child_count()>0) {
child=child->get_child(0);
@ -72,7 +73,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
p_library->tile_set_texture(id,texture);
Vector2 phys_offset = mi->get_offset();
Vector2 phys_offset;
if (mi->is_centered()) {
Size2 s;
@ -112,7 +113,7 @@ void TileSetEditor::_import_scene(Node *scene, Ref<TileSet> p_library, bool p_me
}
p_library->tile_set_texture_offset(id,Vector2());
p_library->tile_set_texture_offset(id,mi->get_offset());
}
}

View File

@ -108,6 +108,11 @@ class ExportDAE(bpy.types.Operator, ExportHelper):
description=("Export all actions for the first armature found in separate DAE files"),
default=False,
)
use_anim_skip_noexp = BoolProperty(
name="Skip (-noexp) Actions",
description="Skip exporting of actions whose name end in (-noexp). Useful to skip control animations.",
default=True,
)
use_anim_optimize = BoolProperty(
name="Optimize Keyframes",
description="Remove double keyframes",

View File

@ -317,6 +317,7 @@ class DaeExporter:
def export_mesh(self,node,armature=None,shapename=None):
mesh = node.data
if (node.data in self.mesh_cache) and shapename==None:
return self.mesh_cache[mesh]
@ -475,7 +476,12 @@ class DaeExporter:
self.writel(S_GEOM,3,'<source id="'+meshid+'-texcoord-'+str(uvi)+'">')
float_values=""
for v in vertices:
try:
float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y)
except:
# I don't understand this weird multi-uv-layer API, but with this it seems to works
float_values+=" 0 0 "
self.writel(S_GEOM,4,'<float_array id="'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices)*2)+'">'+float_values+'</float_array>')
self.writel(S_GEOM,4,'<technique_common>')
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices))+'" stride="2">')
@ -1156,6 +1162,8 @@ class DaeExporter:
for x in bpy.data.actions[:]:
if x.users==0 or x in self.action_constraints:
continue
if (self.config["use_anim_skip_noexp"] and x.name.endswith("-noexp")):
continue
bones=[]
#find bones used