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); 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() { 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("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); Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon);
Dictionary make_atlas(const Vector<Size2>& p_rects);
_Geometry(); _Geometry();
}; };

View File

@ -216,6 +216,14 @@ public:
* Convert the image to another format, as close as it can be done. * Convert the image to another format, as close as it can be done.
*/ */
void convert( Format p_new_format ); 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. * 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

@ -826,7 +826,9 @@ public:
static DVector<Plane> build_box_planes(const Vector3& p_extents); static DVector<Plane> build_box_planes(const Vector3& p_extents);
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_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 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)\ #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(); } 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)\ #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)\ #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]); } 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)\ #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_PTR3R(Image, resized);
VCALL_PTR0R(Image, get_data); VCALL_PTR0R(Image, get_data);
VCALL_PTR3(Image, blit_rect); VCALL_PTR3(Image, blit_rect);
VCALL_PTR1R(Image, converted);
VCALL_PTR0R( AABB, get_area ); VCALL_PTR0R( AABB, get_area );
VCALL_PTR0R( AABB, has_no_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, inverse );
VCALL_PTR0R( Matrix3, transposed ); 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))); ADDFUNC3(IMAGE, IMAGE, Image, resized, INT, "x", INT, "y", INT, "interpolation", varray(((int)Image::INTERPOLATE_BILINEAR)));
ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray()); ADDFUNC0(IMAGE, RAW_ARRAY, Image, get_data, varray());
ADDFUNC3(IMAGE, NIL, Image, blit_rect, IMAGE, "src", RECT2, "src_rect", VECTOR2, "dest", varray(0)); 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()); 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,translated,VECTOR2,"offset",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform,NIL,"v",varray()); ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform,NIL,"v",varray());
ADDFUNC1(MATRIX32,MATRIX32,Matrix32,xform_inv,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()); ADDFUNC2(MATRIX32,MATRIX32,Matrix32,interpolate_with,MATRIX32,"m",REAL,"c",varray());
ADDFUNC0(MATRIX3,MATRIX3,Matrix3,inverse,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(); return fa->get_pos();
}; };
TPDataFA(String p_path) { TPDataFA(const String& p_path) {
fa = FileAccess::open(p_path, FileAccess::READ); fa = FileAccess::open(p_path, FileAccess::READ);
data_name = "File: " + p_path; data_name = "File: " + p_path;
}; };
TPDataFA(FileAccess* p_fa, const String& p_path) {
fa = p_fa;
data_name = "File: " + p_path;
};
~TPDataFA() { ~TPDataFA() {
if (fa) if (fa)
@ -366,6 +372,10 @@ void VideoStreamTheoraplayer::update(float p_time) {
void VideoStreamTheoraplayer::set_file(const String& p_file) { 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) { if (!audio_factory) {
audio_factory = memnew(TPAudioGodotFactory); 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(); std::string file = p_file.replace("res://", "").utf8().get_data();
clip = mgr->createVideoClip(file); clip = mgr->createVideoClip(file);
memdelete(f);
} else { } else {
TheoraDataSource* ds = memnew(TPDataFA(p_file)); TheoraDataSource* ds = memnew(TPDataFA(f, p_file));
try { try {
clip = mgr->createVideoClip(ds); clip = mgr->createVideoClip(ds);

View File

@ -3,6 +3,9 @@ Import('env')
files = [ files = [
'thread_winrt.cpp', 'thread_winrt.cpp',
# '#platform/windows/stream_peer_winsock.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(CCFLAGS=['-g','-pg'])
env.Append(LINKFLAGS=['-pg']) env.Append(LINKFLAGS=['-pg'])
env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/ZW', '/EHsc']) env.Append(CCFLAGS=['/Gd','/GR','/nologo', '/EHsc'])
env.Append(CXXFLAGS=['/TP']) env.Append(CXXFLAGS=['/TP', '/ZW'])
env.Append(CPPFLAGS=['/DMSVC', '/GR', ]) env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
#env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"]) #env.Append(CCFLAGS=['/I'+os.getenv("WindowsSdkDir")+"/Include"])
env.Append(CCFLAGS=['/DWINRT_ENABLED']) env.Append(CCFLAGS=['/DWINRT_ENABLED'])
env.Append(CCFLAGS=['/DWINDOWS_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=['/DRTAUDIO_ENABLED'])
#env.Append(CCFLAGS=['/DWIN32']) #env.Append(CCFLAGS=['/DWIN32'])
env.Append(CCFLAGS=['/DTYPED_METHOD_BIND']) 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: */ /* This file is part of: */
/* GODOT ENGINE */ /* GODOT ENGINE */
@ -28,12 +28,12 @@
/*************************************************************************/ /*************************************************************************/
#include "drivers/gles2/rasterizer_gles2.h" #include "drivers/gles2/rasterizer_gles2.h"
#include "drivers/gles1/rasterizer_gles1.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/nedmalloc/memory_pool_static_nedmalloc.h"
#include "drivers/unix/memory_pool_static_malloc.h" #include "drivers/unix/memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h" #include "os/memory_pool_dynamic_static.h"
#include "drivers/windows/thread_windows.h" #include "thread_winrt.h"
#include "drivers/windows/semaphore_windows.h" //#include "drivers/windows/semaphore_windows.h"
#include "drivers/windows/mutex_windows.h" #include "drivers/windows/mutex_windows.h"
#include "main/main.h" #include "main/main.h"
#include "drivers/windows/file_access_windows.h" #include "drivers/windows/file_access_windows.h"
@ -44,14 +44,22 @@
#include "servers/audio/audio_server_sw.h" #include "servers/audio/audio_server_sw.h"
#include "servers/visual/visual_server_wrap_mt.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 "os/pc_joystick_map.h"
#include "lang_table.h"
#include "os/memory_pool_dynamic_prealloc.h" #include "os/memory_pool_dynamic_prealloc.h"
#include "globals.h" #include "globals.h"
#include "io/marshalls.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 { int OSWinrt::get_video_driver_count() const {
return 2; return 2;
@ -129,59 +137,18 @@ 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; gl_context = p_context;
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);
}
}; };
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) { void OSWinrt::initialize(const VideoMode& p_desired,int p_video_driver,int p_audio_driver) {
main_loop=NULL; main_loop=NULL;
outside=true; outside=true;
gl_context->initialize();
visual_server = memnew( VisualServerRaster(rasterizer) ); visual_server = memnew( VisualServerRaster(rasterizer) );
if (get_render_thread_mode()!=RENDER_THREAD_UNSAFE) { 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) { void OSWinrt::set_clipboard(const String& p_text) {
/*
if (!OpenClipboard(hWnd)) { if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard."); ERR_EXPLAIN("Unable to open clipboard.");
ERR_FAIL(); ERR_FAIL();
@ -255,10 +223,12 @@ void OSWinrt::set_clipboard(const String& p_text) {
SetClipboardData(CF_TEXT, mem); SetClipboardData(CF_TEXT, mem);
CloseClipboard(); CloseClipboard();
*/
}; };
String OSWinrt::get_clipboard() const { String OSWinrt::get_clipboard() const {
/*
String ret; String ret;
if (!OpenClipboard(hWnd)) { if (!OpenClipboard(hWnd)) {
ERR_EXPLAIN("Unable to open clipboard."); ERR_EXPLAIN("Unable to open clipboard.");
@ -295,6 +265,8 @@ String OSWinrt::get_clipboard() const {
CloseClipboard(); CloseClipboard();
return ret; return ret;
*/
return "";
}; };
@ -327,10 +299,6 @@ void OSWinrt::finalize() {
if (rasterizer) if (rasterizer)
memdelete(rasterizer); memdelete(rasterizer);
if (user_proc) {
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
};
spatial_sound_server->finish(); spatial_sound_server->finish();
memdelete(spatial_sound_server); memdelete(spatial_sound_server);
spatial_sound_2d_server->finish(); spatial_sound_2d_server->finish();
@ -355,16 +323,11 @@ void OSWinrt::finalize() {
} }
void OSWinrt::finalize_core() { void OSWinrt::finalize_core() {
memdelete(process_map);
if (mempool_dynamic) if (mempool_dynamic)
memdelete( mempool_dynamic ); memdelete( mempool_dynamic );
if (mempool_static) if (mempool_static)
delete mempool_static; delete mempool_static;
TCPServerWinsock::cleanup();
StreamPeerWinsock::cleanup();
} }
void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) { void OSWinrt::vprint(const char* p_format, va_list p_list, bool p_stderr) {
@ -399,10 +362,7 @@ 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) { void OSWinrt::alert(const String& p_alert,const String& p_title) {
if (!is_no_window_mode_enabled()) print_line("ALERT: "+p_alert);
MessageBoxW(NULL,p_alert.c_str(),p_title.c_str(),MB_OK|MB_ICONEXCLAMATION);
else
print_line("ALERT: "+p_alert);
} }
void OSWinrt::set_mouse_mode(MouseMode p_mode) { void OSWinrt::set_mouse_mode(MouseMode p_mode) {
@ -445,71 +405,16 @@ 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) { 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 (p_rationale && p_rationale[0]) {
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); print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale);
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line); print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
} else {
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
}
} else { } else {
print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code);
print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line);
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 { void OSWinrt::delay_usec(uint32_t p_usec) const {
if (p_usec < 1000) int msec = p_usec < 1000 ? 1 : p_usec / 1000;
Sleep(1);
else // no Sleep()
Sleep(p_usec / 1000); WaitForSingleObjectEx(GetCurrentThread(), msec, false);
} }
uint64_t OSWinrt::get_ticks_usec() const { 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) { Error OSWinrt::set_cwd(const String& p_cwd) {
if (_wchdir(p_cwd.c_str())!=0)
return ERR_CANT_OPEN;
return OK; return OK;
} }
String OSWinrt::get_executable_path() const { String OSWinrt::get_executable_path() const {
wchar_t bufname[4096]; return "";
GetModuleFileNameW(NULL,bufname,4096);
String s= bufname;
print_line("EXEC PATHPó: "+s);
return s;
} }
void OSWinrt::set_icon(const Image& p_icon) { 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 { 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 { String OSWinrt::get_environment(const String& p_var) const {
char* val = getenv(p_var.utf8().get_data());
if (val)
return val;
return ""; return "";
}; };
String OSWinrt::get_stdin_string(bool p_block) { String OSWinrt::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
return fgets(buff,1024,stdin);
};
return String(); return String();
} }
@ -665,23 +554,22 @@ Error OSWinrt::shell_open(String p_uri) {
String OSWinrt::get_locale() const { String OSWinrt::get_locale() const {
Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag; Platform::String ^language = Windows::Globalization::Language::CurrentInputMethodLanguageTag;
return language.Data(); return language->Data();
} }
void OSWinrt::release_rendering_thread() { void OSWinrt::release_rendering_thread() {
//gl_context->release_current(); gl_context->release_current();
} }
void OSWinrt::make_rendering_thread() { void OSWinrt::make_rendering_thread() {
//gl_context->make_current(); gl_context->make_current();
} }
void OSWinrt::swap_buffers() { void OSWinrt::swap_buffers() {
//gl_context->swap_buffers(); gl_context->swap_buffers();
} }
@ -699,6 +587,7 @@ void OSWinrt::run() {
while (!force_quit) { while (!force_quit) {
CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
process_events(); // get rid of pending events process_events(); // get rid of pending events
if (Main::iteration()==true) if (Main::iteration()==true)
break; break;
@ -724,7 +613,7 @@ String OSWinrt::get_data_dir() const {
} }
OSWinrt::OSWinrt(HINSTANCE _hInstance) { OSWinrt::OSWinrt() {
key_event_pos=0; key_event_pos=0;
force_quit=false; force_quit=false;
@ -743,6 +632,8 @@ OSWinrt::OSWinrt(HINSTANCE _hInstance) {
stdo=fopen("stdout.txt","wb"); stdo=fopen("stdout.txt","wb");
#endif #endif
gl_context = NULL;
} }

View File

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

View File

@ -106,9 +106,9 @@ Ref<TileSet> TileMap::get_tileset() const {
return tile_set; 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(); _clear_quadrants();
cell_size=p_size; 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; return cell_size;
} }
@ -171,6 +171,7 @@ void TileMap::_update_dirty_quadrants() {
VisualServer *vs = VisualServer::get_singleton(); VisualServer *vs = VisualServer::get_singleton();
Physics2DServer *ps = Physics2DServer::get_singleton(); Physics2DServer *ps = Physics2DServer::get_singleton();
Vector2 tofs = get_cell_draw_offset();
while (dirty_quadrant_list.first()) { while (dirty_quadrant_list.first()) {
@ -189,7 +190,7 @@ void TileMap::_update_dirty_quadrants() {
Ref<Texture> tex = tile_set->tile_get_texture(c.id); Ref<Texture> tex = tile_set->tile_get_texture(c.id);
Vector2 tile_ofs = tile_set->tile_get_texture_offset(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()) if (!tex.is_valid())
continue; continue;
@ -299,7 +300,11 @@ void TileMap::_recompute_rect_cache() {
for (Map<PosKey,Quadrant>::Element *E=quadrant_map.front();E;E=E->next()) { 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()) if (E==quadrant_map.front())
r_total=r; r_total=r;
else else
@ -323,8 +328,10 @@ void TileMap::_recompute_rect_cache() {
Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) { Map<TileMap::PosKey,TileMap::Quadrant>::Element *TileMap::_create_quadrant(const PosKey& p_qk) {
Matrix32 xform; 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; 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(); 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_parent( q.canvas_item, get_canvas_item() );
VisualServer::get_singleton()->canvas_item_set_transform( q.canvas_item, xform ); 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); 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; rect_cache_dirty=true;
quadrant_order_dirty=true; quadrant_order_dirty=true;
@ -478,8 +484,11 @@ void TileMap::_recreate_quadrants() {
} }
Q->get().cells.insert(E->key()); Q->get().cells.insert(E->key());
_make_quadrant_dirty(Q);
} }
} }
void TileMap::_clear_quadrants() { void TileMap::_clear_quadrants() {
@ -614,6 +623,152 @@ uint32_t TileMap::get_collision_layer_mask() const {
return collision_layer; 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() { 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("set_tileset","tileset:TileSet"),&TileMap::set_tileset);
ObjectTypeDB::bind_method(_MD("get_tileset:TileSet"),&TileMap::get_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("set_cell_size","size"),&TileMap::set_cell_size);
ObjectTypeDB::bind_method(_MD("get_cell_size"),&TileMap::get_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("set_quadrant_size","size"),&TileMap::set_quadrant_size);
ObjectTypeDB::bind_method(_MD("get_quadrant_size"),&TileMap::get_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("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("_clear_quadrants"),&TileMap::_clear_quadrants);
ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants); ObjectTypeDB::bind_method(_MD("_recreate_quadrants"),&TileMap::_recreate_quadrants);
ObjectTypeDB::bind_method(_MD("_update_dirty_quadrants"),&TileMap::_update_dirty_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("_set_tile_data"),&TileMap::_set_tile_data);
ObjectTypeDB::bind_method(_MD("_get_tile_data"),&TileMap::_get_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,"mode",PROPERTY_HINT_ENUM,"Square,Isometric,Custom"),_SCS("set_mode"),_SCS("get_mode"));
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::OBJECT,"tile_set",PROPERTY_HINT_RESOURCE_TYPE,"TileSet"),_SCS("set_tileset"),_SCS("get_tileset")); 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/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::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::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")); ADD_SIGNAL(MethodInfo("settings_changed"));
BIND_CONSTANT( INVALID_CELL ); 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() { TileMap::TileMap() {
@ -678,12 +858,14 @@ TileMap::TileMap() {
pending_update=false; pending_update=false;
quadrant_order_dirty=false; quadrant_order_dirty=false;
quadrant_size=16; quadrant_size=16;
cell_size=64; cell_size=Size2(64,64);
center_x=false; center_x=false;
center_y=false; center_y=false;
collision_layer=1; collision_layer=1;
friction=1; friction=1;
bounce=0; bounce=0;
mode=MODE_SQUARE;
half_offset=HALF_OFFSET_DISABLED;
fp_adjust=0.01; fp_adjust=0.01;
fp_adjust=0.01; fp_adjust=0.01;

View File

@ -37,12 +37,30 @@
class TileMap : public Node2D { class TileMap : public Node2D {
OBJ_TYPE( TileMap, 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; Ref<TileSet> tile_set;
int cell_size; Size2i cell_size;
int quadrant_size; int quadrant_size;
bool center_x,center_y; bool center_x,center_y;
Mode mode;
Matrix32 custom_transform;
HalfOffset half_offset;
union PosKey { union PosKey {
@ -117,6 +135,12 @@ class TileMap : public Node2D {
void _set_tile_data(const DVector<int>& p_data); void _set_tile_data(const DVector<int>& p_data);
DVector<int> _get_tile_data() const; 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: protected:
@ -132,8 +156,8 @@ public:
void set_tileset(const Ref<TileSet>& p_tileset); void set_tileset(const Ref<TileSet>& p_tileset);
Ref<TileSet> get_tileset() const; Ref<TileSet> get_tileset() const;
void set_cell_size(int p_size); void set_cell_size(Size2 p_size);
int get_cell_size() const; Size2 get_cell_size() const;
void set_quadrant_size(int p_size); void set_quadrant_size(int p_size);
int get_quadrant_size() const; int get_quadrant_size() const;
@ -159,10 +183,28 @@ public:
void set_collision_bounce(float p_bounce); void set_collision_bounce(float p_bounce);
float get_collision_bounce() const; 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(); void clear();
TileMap(); TileMap();
~TileMap(); ~TileMap();
}; };
VARIANT_ENUM_CAST(TileMap::Mode);
VARIANT_ENUM_CAST(TileMap::HalfOffset);
#endif // TILE_MAP_H #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() { 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("set_priority","priority"),&Area::set_priority);
ObjectTypeDB::bind_method(_MD("get_priority"),&Area::get_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("set_enable_monitoring","enable"),&Area::set_enable_monitoring);
ObjectTypeDB::bind_method(_MD("is_monitoring_enabled"),&Area::is_monitoring_enabled); 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::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::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,"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; density=0.1;
priority=0; priority=0;
monitoring=false; monitoring=false;
ray_pickable=false; set_ray_pickable(false);
set_enable_monitoring(true); set_enable_monitoring(true);
} }

View File

@ -52,7 +52,7 @@ private:
real_t density; real_t density;
int priority; int priority;
bool monitoring; 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); 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); void set_priority(real_t p_priority);
real_t get_priority() const; 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); void set_enable_monitoring(bool p_enable);
bool is_monitoring_enabled() const; bool is_monitoring_enabled() const;

View File

@ -262,7 +262,7 @@ void Camera::_notification(int p_what) {
Transform Camera::get_camera_transform() const { 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) { 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 else
cm.set_orthogonal(size,viewport_size.get_aspect(),near,far,keep_aspect==KEEP_WIDTH); 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) { void Camera::look_at(const Vector3& p_target, const Vector3& p_up_normal) {
Transform lookat; Transform lookat;
lookat.origin=get_global_transform().origin; lookat.origin=get_camera_transform().origin;
lookat=lookat.looking_at(p_target,p_up_normal); lookat=lookat.looking_at(p_target,p_up_normal);
set_global_transform(lookat); set_global_transform(lookat);
} }

View File

@ -53,8 +53,9 @@ void CollisionObject::_notification(int p_what) {
} else } else
PhysicsServer::get_singleton()->body_set_space(rid,space); PhysicsServer::get_singleton()->body_set_space(rid,space);
_update_pickable();
//get space //get space
} };
case NOTIFICATION_TRANSFORM_CHANGED: { case NOTIFICATION_TRANSFORM_CHANGED: {
@ -63,6 +64,11 @@ void CollisionObject::_notification(int p_what) {
else else
PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform()); PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform());
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
_update_pickable();
} break; } break;
case NOTIFICATION_EXIT_WORLD: { case NOTIFICATION_EXIT_WORLD: {
@ -91,11 +97,11 @@ void CollisionObject::_update_shapes() {
continue; continue;
if (area) if (area)
PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform); PhysicsServer::get_singleton()->area_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
else { else {
PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform); PhysicsServer::get_singleton()->body_add_shape(rid,shapes[i].shape->get_rid(),shapes[i].xform);
if (shapes[i].trigger) if (shapes[i].trigger)
PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger); PhysicsServer::get_singleton()->body_set_shape_as_trigger(rid,i,shapes[i].trigger);
} }
} }
} }
@ -160,18 +166,18 @@ void CollisionObject::_get_property_list( List<PropertyInfo> *p_list) const {
String path="shapes/"+itos(i)+"/"; String path="shapes/"+itos(i)+"/";
p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) ); p_list->push_back( PropertyInfo(Variant::OBJECT,path+"shape",PROPERTY_HINT_RESOURCE_TYPE,"Shape",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); p_list->push_back( PropertyInfo(Variant::TRANSFORM,path+"transform",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) ); p_list->push_back( PropertyInfo(Variant::BOOL,path+"trigger",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR) );
} }
} }
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()) { 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() { 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() { 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("get_shape_transform","shape_idx"),&CollisionObject::get_shape_transform);
ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape); ObjectTypeDB::bind_method(_MD("remove_shape","shape_idx"),&CollisionObject::remove_shape);
ObjectTypeDB::bind_method(_MD("clear_shapes"),&CollisionObject::clear_shapes); 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("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_capture_input_on_drag"),&CollisionObject::get_capture_input_on_drag);
ObjectTypeDB::bind_method(_MD("get_rid"),&CollisionObject::get_rid); 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_enter"));
ADD_SIGNAL( MethodInfo("mouse_exit")); 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")); 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; rid=p_rid;
area=p_area; area=p_area;
capture_input_on_drag=false;
ray_pickable=true;
if (p_area) { if (p_area) {
PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID()); PhysicsServer::get_singleton()->area_attach_object_instance_ID(rid,get_instance_ID());
} else { } else {
@ -321,6 +354,7 @@ CollisionObject::CollisionObject() {
capture_input_on_drag=false; capture_input_on_drag=false;
ray_pickable=true;
//owner= //owner=

View File

@ -51,9 +51,10 @@ class CollisionObject : public Spatial {
}; };
bool capture_input_on_drag; bool capture_input_on_drag;
bool ray_pickable;
Vector<ShapeData> shapes; Vector<ShapeData> shapes;
void _update_pickable();
void _update_shapes(); void _update_shapes();
friend class CollisionShape; friend class CollisionShape;
@ -69,7 +70,7 @@ protected:
void _get_property_list( List<PropertyInfo> *p_list) const; void _get_property_list( List<PropertyInfo> *p_list) const;
static void _bind_methods(); static void _bind_methods();
friend class Viewport; 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_enter();
virtual void _mouse_exit(); virtual void _mouse_exit();
@ -87,9 +88,13 @@ public:
void set_shape_as_trigger(int p_shape_idx, bool p_trigger); void set_shape_as_trigger(int p_shape_idx, bool p_trigger);
bool is_shape_set_as_trigger(int p_shape_idx) const; 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); void set_capture_input_on_drag(bool p_capture);
bool get_capture_input_on_drag() const; bool get_capture_input_on_drag() const;
_FORCE_INLINE_ RID get_rid() const { return rid; } _FORCE_INLINE_ RID get_rid() const { return rid; }
CollisionObject(); 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/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_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()); List<Polygon>::Element *P=nm.polygons.push_back(Polygon());
Polygon &p=P->get(); Polygon &p=P->get();
p.owner=&nm;
Vector<int> poly = nm.navmesh->get_polygon(i); Vector<int> poly = nm.navmesh->get_polygon(i);
int plen=poly.size(); 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++; int id = last_id++;
NavMesh nm; NavMesh nm;
nm.linked=false; nm.linked=false;
nm.navmesh=p_mesh; nm.navmesh=p_mesh;
nm.xform=p_xform; nm.xform=p_xform;
nm.owner=p_owner;
navmesh_map[id]=nm; navmesh_map[id]=nm;
_navmesh_link(id); _navmesh_link(id);
@ -453,6 +455,7 @@ Vector3 Navigation::get_closest_point_to_segment(const Vector3& p_from,const Vec
bool use_collision=false; bool use_collision=false;
Vector3 closest_point; Vector3 closest_point;
float closest_point_d=1e20; float closest_point_d=1e20;
NavMesh *closest_navmesh=NULL;
for (Map<int,NavMesh>::Element*E=navmesh_map.front();E;E=E->next()) { 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; closest_point=inters;
use_collision=true; use_collision=true;
closest_point_d=p_from.distance_to(inters); closest_point_d=p_from.distance_to(inters);
closest_navmesh=p.owner;
} else if (closest_point_d > inters.distance_to(p_from)){ } else if (closest_point_d > inters.distance_to(p_from)){
closest_point=inters; closest_point=inters;
closest_point_d=p_from.distance_to(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_d=d;
closest_point=b; 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; return closest_point;
} }
@ -577,7 +587,7 @@ Vector3 Navigation::get_up_vector() const{
void Navigation::_bind_methods() { 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_set_transform","id","xform"),&Navigation::navmesh_set_transform);
ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove); ObjectTypeDB::bind_method(_MD("navmesh_remove","id"),&Navigation::navmesh_remove);

View File

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

View File

@ -129,7 +129,7 @@ void NavigationMeshInstance::set_enabled(bool p_enabled) {
if (navmesh.is_valid()) { 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()) { 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; break;
} }
@ -205,7 +205,7 @@ void NavigationMeshInstance::set_navigation_mesh(const Ref<NavigationMesh>& p_na
navmesh=p_navmesh; navmesh=p_navmesh;
if (navigation && navmesh.is_valid() && enabled) { 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(); update_gizmo();

View File

@ -66,6 +66,9 @@ void Joint::_update_joint(bool p_only_free) {
joint = _configure_joint(body_a,body_b); 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()) { if (body_b && joint.is_valid()) {
ba=body_a->get_rid(); 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) { void Joint::_notification(int p_what) {
switch(p_what) { switch(p_what) {
@ -117,8 +134,6 @@ void Joint::_notification(int p_what) {
case NOTIFICATION_EXIT_SCENE: { case NOTIFICATION_EXIT_SCENE: {
if (joint.is_valid()) { if (joint.is_valid()) {
_update_joint(true); _update_joint(true);
PhysicsServer::get_singleton()->free(joint); PhysicsServer::get_singleton()->free(joint);
joint=RID(); 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("set_node_b","node"), &Joint::set_node_b );
ObjectTypeDB::bind_method( _MD("get_node_b"), &Joint::get_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_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::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() { Joint::Joint() {
solver_priority=1;
} }

View File

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

View File

@ -179,7 +179,7 @@ void VehicleWheel::set_damping_compression(float p_value){
} }
float VehicleWheel::get_damping_compression() const{ float VehicleWheel::get_damping_compression() const{
return m_wheelsDampingRelaxation; return m_wheelsDampingCompression;
} }
void VehicleWheel::set_damping_relaxation(float p_value){ void VehicleWheel::set_damping_relaxation(float p_value){
@ -745,11 +745,12 @@ void VehicleBody::_update_friction(PhysicsDirectBodyState *s) {
{ {
if (engine_force != 0.f) if (engine_force != 0.f)
{ {
rollingFriction = engine_force* s->get_step(); rollingFriction = -engine_force* s->get_step();
} else } else
{ {
real_t defaultRollingFrictionImpulse = 0.f; 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); btVehicleWheelContactPoint contactPt(s,wheelInfo.m_raycastInfo.m_groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
rollingFriction = _calc_rolling_friction(contactPt); rollingFriction = _calc_rolling_friction(contactPt);
} }
@ -1009,9 +1010,9 @@ void VehicleBody::_bind_methods(){
ObjectTypeDB::bind_method(_MD("_direct_state_changed"),&VehicleBody::_direct_state_changed); 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/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.01,1024.0,0.01"),_SCS("set_brake"),_SCS("get_brake")); 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,"0.01,1024.0,0.01"),_SCS("set_steering"),_SCS("get_steering")); 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/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")); 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) { 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_pos"),&AnimationPlayer::get_current_animation_pos);
ObjectTypeDB::bind_method(_MD("get_current_animation_length"),&AnimationPlayer::get_current_animation_length); 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::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")); 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_pos() const;
float get_current_animation_length() const; float get_current_animation_length() const;
void advance(float p_time);
void set_root(const NodePath& p_root); void set_root(const NodePath& p_root);
NodePath get_root() const; 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() { void EventPlayer::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_stream","stream:Stream"),&EventPlayer::set_stream); ObjectTypeDB::bind_method(_MD("set_stream","stream:EventStream"),&EventPlayer::set_stream);
ObjectTypeDB::bind_method(_MD("get_stream:Stream"),&EventPlayer::get_stream); ObjectTypeDB::bind_method(_MD("get_stream:EventStream"),&EventPlayer::get_stream);
ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play); ObjectTypeDB::bind_method(_MD("play"),&EventPlayer::play);
ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop); ObjectTypeDB::bind_method(_MD("stop"),&EventPlayer::stop);

View File

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

View File

@ -397,6 +397,7 @@ void Label::regenerate_word_cache() {
} }
if (current=='\n') { if (current=='\n') {
insert_newline=true; insert_newline=true;
} else { } 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) { if (!autowrap) {
@ -535,7 +536,7 @@ void Label::set_percent_visible(float p_percent) {
if (p_percent<0) if (p_percent<0)
set_visible_characters(-1); set_visible_characters(-1);
else else
set_visible_characters(get_total_character_count()*p_percent); set_visible_characters(get_total_character_count()*p_percent);
percent_visible=p_percent; percent_visible=p_percent;
} }

View File

@ -164,6 +164,9 @@ void Viewport::_parent_visibility_changed() {
Control *c = parent->cast_to<Control>(); Control *c = parent->cast_to<Control>();
VisualServer::get_singleton()->canvas_item_set_visible(canvas_item,c->is_visible()); 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) { if (obj) {
CollisionObject *co = obj->cast_to<CollisionObject>(); CollisionObject *co = obj->cast_to<CollisionObject>();
if (co) { if (co) {
co->_input_event(ev,Vector3(),Vector3(),0); co->_input_event(camera,ev,Vector3(),Vector3(),0);
captured=true; captured=true;
if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) { if (ev.type==InputEvent::MOUSE_BUTTON && ev.mouse_button.button_index==1 && !ev.mouse_button.pressed) {
physics_object_capture=0; physics_object_capture=0;
@ -416,7 +419,7 @@ void Viewport::_notification(int p_what) {
if (last_id) { if (last_id) {
if (ObjectDB::get_instance(last_id)) { if (ObjectDB::get_instance(last_id)) {
//good, exists //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) { 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; 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); bool col = space->intersect_ray(from,from+dir*10000,result,Set<RID>(),0xFFFFFFFF,0xFFFFFFFF);
ObjectID new_collider=0; ObjectID new_collider=0;
if (col) { if (col) {
if (result.collider) { if (result.collider) {
CollisionObject *co = result.collider->cast_to<CollisionObject>(); CollisionObject *co = result.collider->cast_to<CollisionObject>();
if (co) { 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_object=co;
last_id=result.collider_id; last_id=result.collider_id;
new_collider=last_id; new_collider=last_id;
@ -541,7 +547,7 @@ Rect2 Viewport::get_rect() const {
void Viewport::_update_listener() { 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()); SpatialSoundServer::get_singleton()->listener_set_space(listener,find_world()->get_sound_space());
} else { } else {
SpatialSoundServer::get_singleton()->listener_set_space(listener,RID()); SpatialSoundServer::get_singleton()->listener_set_space(listener,RID());
@ -552,7 +558,7 @@ void Viewport::_update_listener() {
void Viewport::_update_listener_2d() { 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()); SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,find_world_2d()->get_sound_space());
else else
SpatialSound2DServer::get_singleton()->listener_set_space(listener_2d,RID()); 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/sample_player_2d.h"
#include "scene/2d/screen_button.h" #include "scene/2d/screen_button.h"
#include "scene/2d/remote_transform_2d.h" #include "scene/2d/remote_transform_2d.h"
#include "scene/2d/y_sort.h"
#include "scene/2d/position_2d.h" #include "scene/2d/position_2d.h"
#include "scene/2d/tile_map.h" #include "scene/2d/tile_map.h"
@ -491,6 +492,7 @@ void register_scene_types() {
ObjectTypeDB::register_type<VisibilityNotifier2D>(); ObjectTypeDB::register_type<VisibilityNotifier2D>();
ObjectTypeDB::register_type<VisibilityEnabler2D>(); ObjectTypeDB::register_type<VisibilityEnabler2D>();
ObjectTypeDB::register_type<Polygon2D>(); ObjectTypeDB::register_type<Polygon2D>();
ObjectTypeDB::register_type<YSort>();
ObjectTypeDB::set_type_enabled("CollisionShape2D",false); ObjectTypeDB::set_type_enabled("CollisionShape2D",false);
ObjectTypeDB::set_type_enabled("CollisionPolygon2D",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_INDEX(p_idx,tracks.size());
ERR_FAIL_COND(tracks[p_idx]->type!=TYPE_TRANSFORM); 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 { } else {
Quat r02 = (q0.inverse() * q2).normalized(); Quat r02 = (q0.inverse() * q2).normalized();
Quat r01 = (q0.inverse() * q1).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); r02.get_axis_and_angle(v02,a02);
r01.get_axis_and_angle(v01,a01); r01.get_axis_and_angle(v01,a01);
if (Math::abs(a02)>p_max_optimizable_angle)
continue;
if (v01.dot(v02)<0) { if (v01.dot(v02)<0) {
//make sure both rotations go the same way to compare //make sure both rotations go the same way to compare
v02=-v02; 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; 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++) { for(int i=0;i<tracks.size();i++) {
if (tracks[i]->type==TYPE_TRANSFORM) 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; 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: protected:
@ -271,7 +271,7 @@ public:
void clear(); 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();
~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); p_node->get_property_list(&plist);
for (List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { 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; continue;
}
String name = E->get().name; String name = E->get().name;
Variant value = p_node->get( 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; continue;
}
if (nd.instance>=0) { if (nd.instance>=0) {
//only save changed properties in instance //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; continue;
if (instance_state[name]==value) }*/
if (instance_state[name]==value) {
continue; 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) { AreaPairSW::AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape) {
body=p_body; body=p_body;
area=p_area; area=p_area;
body_shape=p_body_shape; 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; colliding=false;
body->add_constraint(this,0); body->add_constraint(this,0);
area->add_constraint(this); 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; return;
} }
for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) { for (Map<BodyKey,BodyState>::Element *E=monitored_bodies.front();E;E=E->next()) {
if (E->get().state==0) if (E->get().state==0)
@ -182,8 +180,8 @@ AreaSW::AreaSW() : CollisionObjectSW(TYPE_AREA), monitor_query_list(this), move
point_attenuation=1; point_attenuation=1;
density=0.1; density=0.1;
priority=0; 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 point_attenuation;
float density; float density;
int priority; int priority;
bool ray_pickable;
ObjectID monitor_callback_id; ObjectID monitor_callback_id;
StringName monitor_callback_method; StringName monitor_callback_method;
@ -139,8 +138,6 @@ public:
_FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ void remove_constraint( ConstraintSW* p_constraint) { constraints.erase(p_constraint); }
_FORCE_INLINE_ const Set<ConstraintSW*>& get_constraints() const { return constraints; } _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; space=NULL;
instance_id=0; instance_id=0;
layer_mask=1; layer_mask=1;
ray_pickable=true;
} }

View File

@ -94,6 +94,9 @@ protected:
virtual void _shapes_changed()=0; virtual void _shapes_changed()=0;
void _set_space(SpaceSW *space); void _set_space(SpaceSW *space);
bool ray_pickable;
CollisionObjectSW(Type p_type); CollisionObjectSW(Type p_type);
public: public:
@ -119,6 +122,9 @@ public:
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ SpaceSW* get_space() const { return space; } _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_ void set_layer_mask(uint32_t p_mask) { layer_mask=p_mask; }
_FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; } _FORCE_INLINE_ uint32_t get_layer_mask() const { return layer_mask; }

View File

@ -38,12 +38,13 @@ class ConstraintSW {
uint64_t island_step; uint64_t island_step;
ConstraintSW *island_next; ConstraintSW *island_next;
ConstraintSW *island_list_next; ConstraintSW *island_list_next;
int priority;
RID self; RID self;
protected: 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: public:
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; } _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_ BodySW **get_body_ptr() const { return _body_ptr; }
_FORCE_INLINE_ int get_body_count() const { return _body_count; } _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 bool setup(float p_step)=0;
virtual void solve(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 */ /* 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); 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 { PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const {
JointSW *joint = joint_owner.get(p_joint); 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_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 */ /* 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); 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 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 #if 0
virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); 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; 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; real_t min_d=1e10;
for(int i=0;i<amount;i++) { for(int i=0;i<amount;i++) {
if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask)) if (!_match_object_type_query(space->intersection_query_results[i],p_layer_mask,p_object_type_mask))
continue; 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; continue;
if (p_exclude.has( space->intersection_query_results[i]->get_self())) 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)) { 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); Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point); shape_point=xform.xform(shape_point);

View File

@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/ /*************************************************************************/
#include "step_sw.h" #include "step_sw.h"
#include "joints_sw.h"
void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) { void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island) {
@ -68,14 +68,41 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){ void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
for(int i=0;i<p_iterations;i++) { int at_priority=1;
ConstraintSW *ci=p_island; while(p_island) {
while(ci) {
ci->solve(p_delta); for(int i=0;i<p_iterations;i++) {
ci=ci->get_island_next();
ConstraintSW *ci=p_island;
while(ci) {
ci->solve(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) { 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_vector=Vector2(0,-1);
gravity_is_point=false; gravity_is_point=false;
point_attenuation=1; point_attenuation=1;
density=0.1; density=0.1;
priority=0; priority=0;
monitor_callback_id=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; colliding=false;
body->add_constraint(this,0); body->add_constraint(this,0);
area->add_constraint(this); 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_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 */ /* JOINT API */
BIND_CONSTANT( JOINT_PIN ); 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_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("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); 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_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 */ /* JOINT API */
enum JointType { enum JointType {
@ -464,6 +468,8 @@ public:
virtual JointType joint_get_type(RID p_joint) const=0; 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; 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_virtual_type<Physics2DShapeQueryResult>();
ObjectTypeDB::register_type<Physics2DShapeQueryParameters>(); ObjectTypeDB::register_type<Physics2DShapeQueryParameters>();
ObjectTypeDB::register_type<PhysicsShapeQueryParameters>();
ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>(); ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>();
ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>(); ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>();
ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>(); ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>();

View File

@ -879,10 +879,13 @@ void SpatialSoundServerSW::update(float p_delta) {
float volume_attenuation = 0.0; float volume_attenuation = 0.0;
float air_absorption_hf_cutoff = 0.0; float air_absorption_hf_cutoff = 0.0;
float air_absorption = 0.0; float air_absorption = 0.0;
float pitch_scale=0.0; float pitch_scale=1.0;
Vector3 panning; Vector3 panning;
//print_line("listeners: "+itos(space->listeners.size()));
for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
Listener *listener=listener_owner.get(L->get()); 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_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
float attenuation=1; float attenuation=1;
//print_line("DIST MIN: "+rtos(distance_min));
//print_line("DIST MAX: "+rtos(distance_max));
if (distance_max>0) { if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max); 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]; 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+=weight*absorption;
air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff; air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
panning+=vpanning*weight; 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; reverb_send*=volume_scale;
int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_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."); ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
to_disable.push_back(ActiveVoice(source,voice)); // oh well.. to_disable.push_back(ActiveVoice(source,voice)); // oh well..
continue; //invalid mix rate, disabling continue; //invalid mix rate, disabling

View File

@ -904,7 +904,7 @@ void SpatialSound2DServerSW::update(float p_delta) {
if (distance_max>0) { if (distance_max>0) {
distance = CLAMP(distance,distance_min,distance_max); 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]; 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) { 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 ); Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!camera); ERR_FAIL_COND(!camera);
camera->type=Camera::PERSPECTIVE; camera->type=Camera::PERSPECTIVE;
@ -1226,7 +1226,7 @@ void VisualServerRaster::camera_set_transform(RID p_camera,const Transform& p_tr
VS_CHANGED; VS_CHANGED;
Camera *camera = camera_owner.get( p_camera ); Camera *camera = camera_owner.get( p_camera );
ERR_FAIL_COND(!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); 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) { void VisualServerRaster::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) {
VS_CHANGED; VS_CHANGED;
@ -5591,26 +5600,30 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
float opacity = ci->opacity * p_opacity; 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 child_item_count=ci->child_items.size();
int top_item_count=0; CanvasItem **child_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*));
CanvasItem **top_items=(CanvasItem**)alloca(child_item_count*sizeof(CanvasItem*)); copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*));
if (ci->clip) { if (ci->clip) {
rasterizer->canvas_set_clip(true,global_rect); rasterizer->canvas_set_clip(true,global_rect);
canvas_clip=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++) { for(int i=0;i<child_item_count;i++) {
if (child_items[i]->ontop) if (child_items[i]->ontop)
top_items[top_item_count++]=child_items[i]; continue;
else { _render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
_render_canvas_item(child_items[i],xform,p_clip_rect,opacity);
}
} }
#endif
if (s!=0) { 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); 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++) { if (!child_items[i]->ontop)
continue;
_render_canvas_item(top_items[i],xform,p_clip_rect,opacity); _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) { if (ci->clip) {
rasterizer->canvas_set_clip(false,Rect2()); rasterizer->canvas_set_clip(false,Rect2());

View File

@ -328,7 +328,7 @@ class VisualServerRaster : public VisualServer {
struct CanvasItem { struct CanvasItem {
@ -446,13 +446,14 @@ class VisualServerRaster : public VisualServer {
bool clip; bool clip;
bool visible; bool visible;
bool ontop; bool ontop;
bool sort_y;
float opacity; float opacity;
float self_opacity; float self_opacity;
MaterialBlendMode blend_mode; MaterialBlendMode blend_mode;
RID viewport; RID viewport;
mutable bool custom_rect; mutable bool custom_rect;
mutable bool rect_dirty; mutable bool rect_dirty;
mutable Rect2 rect; mutable Rect2 rect;
Vector<Command*> commands; Vector<Command*> commands;
@ -460,11 +461,18 @@ class VisualServerRaster : public VisualServer {
const Rect2& get_rect() const; 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;}; 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(); } ~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 { 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_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_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_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_clear(RID p_item);
virtual void canvas_item_raise(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_set_blend_mode,RID, MaterialBlendMode );
FUNC2(canvas_item_add_clip_ignore,RID, bool ); 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_clear,RID);
FUNC1(canvas_item_raise,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_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_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_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_clear(RID p_item)=0;
virtual void canvas_item_raise(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") { if (name=="instance_visual_scene") {
state.root_visual_scene=_uri_to_id(parser.get_attribute_value("url")); 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") { } if (name=="instance_physics_scene") {
state.root_physics_scene=_uri_to_id(parser.get_attribute_value("url")); 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... ERR_FAIL_COND_V( !state.scene_map.has( nodeid ), false); //weird, it should have it...
NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]); NodeJoint *nj = SAFE_CAST<NodeJoint*>(state.scene_map[nodeid]);
ERR_FAIL_COND_V(!nj,false); 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 ERR_FAIL_COND_V( !nj->owner,false ); //weird, node should have a skeleton owner
NodeSkeleton *sk = nj->owner; NodeSkeleton *sk = nj->owner;

View File

@ -92,6 +92,7 @@ public:
String gradient_image; String gradient_image;
bool disable_filter;
bool round_advance; bool round_advance;
@ -153,6 +154,8 @@ public:
color_use_monochrome=p_value; color_use_monochrome=p_value;
else if (n=="advanced/round_advance") else if (n=="advanced/round_advance")
round_advance=p_value; round_advance=p_value;
else if (n=="advanced/disable_filter")
disable_filter=p_value;
else else
return false; return false;
@ -217,6 +220,8 @@ public:
r_ret=color_use_monochrome; r_ret=color_use_monochrome;
else if (n=="advanced/round_advance") else if (n=="advanced/round_advance")
r_ret=round_advance; r_ret=round_advance;
else if (n=="advanced/disable_filter")
r_ret=disable_filter;
else else
return false; return false;
@ -265,6 +270,7 @@ public:
} }
p_list->push_back(PropertyInfo(Variant::BOOL,"color/monochrome")); 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/round_advance"));
p_list->push_back(PropertyInfo(Variant::BOOL,"advanced/disable_filter"));
} }
@ -302,6 +308,7 @@ public:
color_use_monochrome=false; color_use_monochrome=false;
round_advance=true; round_advance=true;
disable_filter=false;
} }
@ -331,6 +338,7 @@ public:
color_use_monochrome=false; color_use_monochrome=false;
round_advance=true; 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 space_space = from->get_option("extra_space/space");
int top_space = from->get_option("extra_space/top"); int top_space = from->get_option("extra_space/top");
int bottom_space = from->get_option("extra_space/bottom"); int bottom_space = from->get_option("extra_space/bottom");
bool disable_filter = from->get_option("advanced/disable_filter");
Ref<Font> font; Ref<Font> font;
@ -1279,7 +1288,12 @@ Ref<Font> EditorFontImportPlugin::generate_font(const Ref<ResourceImportMetadata
//register texures //register texures
{ {
Ref<ImageTexture> t = memnew(ImageTexture); 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 ); t->set_storage( ImageTexture::STORAGE_COMPRESS_LOSSLESS );
font->add_texture(t); 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) if (p_clip>=0 && collada.state.animation_clips[p_clip].end)
anim_length=collada.state.animation_clips[p_clip].end; anim_length=collada.state.animation_clips[p_clip].end;
while(f<collada.state.animation_length) { while(f<anim_length) {
if (f>=collada.state.animation_length) if (f>=anim_length)
f=collada.state.animation_length; f=anim_length;
base_snapshots.push_back(f); base_snapshots.push_back(f);
f+=snapshot_interval; f+=snapshot_interval;

View File

@ -40,6 +40,7 @@
#include "scene/3d/body_shape.h" #include "scene/3d/body_shape.h"
#include "scene/3d/physics_body.h" #include "scene/3d/physics_body.h"
#include "scene/3d/portal.h" #include "scene/3d/portal.h"
#include "scene/3d/vehicle_body.h"
#include "os/os.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_BILLBOARDS,"Create","Create Billboards (-bb)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_IMPOSTORS,"Create","Create Impostors (-imp:dist)",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_LODS,"Create","Create LODs (-lod:dist)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Cars (-car)",true}, {EditorSceneImportPlugin::SCENE_FLAG_CREATE_CARS,"Create","Create Vehicles (-vehicle)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_WHEELS,"Create","Create Car Wheels (-wheel)",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_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} {-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 (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) {
if (isroot) if (isroot)
@ -1262,6 +1275,46 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
p_node->replace_by(nmi); p_node->replace_by(nmi);
memdelete(p_node); memdelete(p_node);
p_node=nmi; 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>()) { } 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_ALPHA=1<<15,
SCENE_FLAG_DETECT_VCOLOR=1<<16, SCENE_FLAG_DETECT_VCOLOR=1<<16,
SCENE_FLAG_CREATE_NAVMESH=1<<17, SCENE_FLAG_CREATE_NAVMESH=1<<17,
SCENE_FLAG_DETECT_LIGHTMAP_LAYER=1<<18,
SCENE_FLAG_REMOVE_NOIMP=1<<24, SCENE_FLAG_REMOVE_NOIMP=1<<24,
SCENE_FLAG_IMPORT_ANIMATIONS=1<<25, SCENE_FLAG_IMPORT_ANIMATIONS=1<<25,

View File

@ -64,6 +64,8 @@ void SamplePlayerEditor::_play() {
return; return;
node->call("play",samples->get_item_text( samples->get_selected() )); node->call("play",samples->get_item_text( samples->get_selected() ));
stop->set_pressed(false);
play->set_pressed(true);
} }
void SamplePlayerEditor::_stop() { void SamplePlayerEditor::_stop() {
@ -74,6 +76,9 @@ void SamplePlayerEditor::_stop() {
return; return;
node->call("stop_all"); 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"); call_deferred("update_transform_gizmo_view");
} break; } 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); _menu_option(VIEW_PERSPECTIVE);
if (env != camera->get_environment().is_valid()) if (env != camera->get_environment().is_valid())
_menu_option(VIEW_ENVIRONMENT); _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["distance"]=cursor.distance;
d["use_environment"]=camera->get_environment().is_valid(); d["use_environment"]=camera->get_environment().is_valid();
d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL; d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL;
d["listener"]=viewport->is_audio_listener();
return d; return d;
} }
@ -2147,6 +2164,9 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_separator(); view_menu->get_popup()->add_separator();
view_menu->get_popup()->add_check_item("Environment",VIEW_ENVIRONMENT); 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()->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_separator();
view_menu->get_popup()->add_item("Selection (F)",VIEW_CENTER_TO_SELECTION); 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); 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; previewing=NULL;
preview=NULL; preview=NULL;
gizmo_scale=1.0; 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"); 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_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 { class SpatialEditorViewport : public Control {
OBJ_TYPE( SpatialEditorViewport, Control ); OBJ_TYPE( SpatialEditorViewport, Control );
friend class SpatialEditor;
enum { enum {
VIEW_TOP, VIEW_TOP,
@ -78,7 +78,8 @@ class SpatialEditorViewport : public Control {
VIEW_ALIGN_SELECTION_WITH_VIEW, VIEW_ALIGN_SELECTION_WITH_VIEW,
VIEW_PERSPECTIVE, VIEW_PERSPECTIVE,
VIEW_ENVIRONMENT, VIEW_ENVIRONMENT,
VIEW_ORTHOGONAL VIEW_ORTHOGONAL,
VIEW_AUDIO_LISTENER,
}; };
enum { enum {
GIZMO_BASE_LAYER=25 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 = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse(); 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) { switch(p_event.type) {
@ -218,7 +218,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
if (mb.mod.shift) { if (mb.mod.shift) {
tool=TOOL_SELECTING; 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.pos=selection_begin;
selection.size=Point2(0,0); selection.size=Point2(0,0);
selection_active=true; selection_active=true;
@ -229,7 +229,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) {
int id = get_selected_tile(); int id = get_selected_tile();
if (id!=TileMap::INVALID_CELL) { if (id!=TileMap::INVALID_CELL) {
tool=TOOL_PAINTING; 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(); paint_undo.clear();
CellOp op; CellOp op;
op.idx = node->get_cell(local.x,local.y); 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) { } else if (mb.pressed && tool==TOOL_NONE) {
tool=TOOL_ERASING; 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(); paint_undo.clear();
CellOp op; CellOp op;
op.idx = node->get_cell(local.x,local.y); 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; 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) { if (new_over_tile!=over_tile) {
over_tile=new_over_tile; over_tile=new_over_tile;
@ -469,44 +469,104 @@ void TileMapEditor::_canvas_draw() {
if (!node) if (!node)
return; 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 = CanvasItemEditor::get_singleton()->get_canvas_transform() * node->get_global_transform();
Matrix32 xform_inv = xform.affine_inverse(); Matrix32 xform_inv = xform.affine_inverse();
Size2 screen_size=canvas_item_editor->get_size(); Size2 screen_size=canvas_item_editor->get_size();
Rect2 aabb; {
aabb.pos=xform_inv.xform(Vector2()); Rect2 aabb;
aabb.expand_to(xform_inv.xform(Vector2(0,screen_size.height))); aabb.pos=node->world_to_map(xform_inv.xform(Vector2()));
aabb.expand_to(xform_inv.xform(Vector2(screen_size.width,0))); aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(0,screen_size.height))));
aabb.expand_to(xform_inv.xform(screen_size)); aabb.expand_to(node->world_to_map(xform_inv.xform(Vector2(screen_size.width,0))));
Rect2i si=aabb; 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(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.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); 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(xform.xform(Point2(si.pos.x,ofs)),xform.xform(Point2(si.pos.x+si.size.x,ofs)),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;
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);
} }
if (selection_active) { if (selection_active) {
Vector<Vector2> points; Vector<Vector2> points;
points.push_back( xform.xform( selection.pos * cell_size) ); points.push_back( xform.xform( node->map_to_world(( selection.pos ) )));
points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,0)) * cell_size) ); points.push_back( xform.xform( node->map_to_world((selection.pos+Point2(selection.size.x+1,0)) ) ));
points.push_back( xform.xform( (selection.pos+Point2(selection.size.x+1,selection.size.y+1)) * cell_size) ); 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( (selection.pos+Point2(0,selection.size.y+1)) * cell_size) ); 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); Color col=Color(0.2,0.8,1,0.4);
canvas_item_editor->draw_colored_polygon(points,col); canvas_item_editor->draw_colored_polygon(points,col);
@ -515,15 +575,22 @@ void TileMapEditor::_canvas_draw() {
if (mouse_over){ if (mouse_over){
const Vector2 endpoints[4]={ 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) ,
( 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; Color col;
if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL) if (node->get_cell(over_tile.x,over_tile.y)!=TileMap::INVALID_CELL)
col=Color(0.2,0.8,1.0,0.8); col=Color(0.2,0.8,1.0,0.8);
@ -542,10 +609,10 @@ void TileMapEditor::_canvas_draw() {
Vector<Vector2> points; Vector<Vector2> points;
points.push_back( xform.xform( duplicate.pos * cell_size) ); points.push_back( xform.xform( node->map_to_world(duplicate.pos ) ));
points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,0)) * cell_size) ); points.push_back( xform.xform( node->map_to_world((duplicate.pos+Point2(duplicate.size.x+1,0)) ) ));
points.push_back( xform.xform( (duplicate.pos+Point2(duplicate.size.x+1,duplicate.size.y+1)) * cell_size) ); 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( (duplicate.pos+Point2(0,duplicate.size.y+1)) * cell_size) ); 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); Color col=Color(0.2,1.0,0.8,0.4);
canvas_item_editor->draw_colored_polygon(points,col); canvas_item_editor->draw_colored_polygon(points,col);
@ -562,18 +629,19 @@ void TileMapEditor::_canvas_draw() {
Ref<Texture> t = ts->tile_get_texture(st); Ref<Texture> t = ts->tile_get_texture(st);
if (t.is_valid()) { if (t.is_valid()) {
Rect2 r = ts->tile_get_region(st); Vector2 from = xform.xform(ts->tile_get_texture_offset(st)+node->map_to_world(over_tile)+node->get_cell_draw_offset());
Size2 sc = (endpoints[2]-endpoints[0])/cell_size; Rect2 r = ts->tile_get_region(st);
Size2 sc = xform.get_scale();
if (mirror_x->is_pressed()) if (mirror_x->is_pressed())
sc.x*=-1.0; sc.x*=-1.0;
if (mirror_y->is_pressed()) if (mirror_y->is_pressed())
sc.y*=-1.0; sc.y*=-1.0;
if (r==Rect2()) { 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 { } 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); Node *child = scene->get_child(i);
if (!child->cast_to<Sprite>()) { if (!child->cast_to<Sprite>()) {
if (child->get_child_count()>0) { if (child->get_child_count()>0) {
child=child->get_child(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); p_library->tile_set_texture(id,texture);
Vector2 phys_offset = mi->get_offset(); Vector2 phys_offset;
if (mi->is_centered()) { if (mi->is_centered()) {
Size2 s; 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"), description=("Export all actions for the first armature found in separate DAE files"),
default=False, 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( use_anim_optimize = BoolProperty(
name="Optimize Keyframes", name="Optimize Keyframes",
description="Remove double keyframes", description="Remove double keyframes",

View File

@ -317,6 +317,7 @@ class DaeExporter:
def export_mesh(self,node,armature=None,shapename=None): def export_mesh(self,node,armature=None,shapename=None):
mesh = node.data
if (node.data in self.mesh_cache) and shapename==None: if (node.data in self.mesh_cache) and shapename==None:
return self.mesh_cache[mesh] return self.mesh_cache[mesh]
@ -475,7 +476,12 @@ class DaeExporter:
self.writel(S_GEOM,3,'<source id="'+meshid+'-texcoord-'+str(uvi)+'">') self.writel(S_GEOM,3,'<source id="'+meshid+'-texcoord-'+str(uvi)+'">')
float_values="" float_values=""
for v in vertices: for v in vertices:
float_values+=" "+str(v.uv[uvi].x)+" "+str(v.uv[uvi].y) 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,'<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,'<technique_common>')
self.writel(S_GEOM,4,'<accessor source="#'+meshid+'-texcoord-'+str(uvi)+'-array" count="'+str(len(vertices))+'" stride="2">') 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[:]: for x in bpy.data.actions[:]:
if x.users==0 or x in self.action_constraints: if x.users==0 or x in self.action_constraints:
continue continue
if (self.config["use_anim_skip_noexp"] and x.name.endswith("-noexp")):
continue
bones=[] bones=[]
#find bones used #find bones used