mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 22:40:12 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into line-entity
This commit is contained in:
commit
f647db3bf0
31 changed files with 1674 additions and 424 deletions
93
examples/ajt-test.js
Normal file
93
examples/ajt-test.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
var spawnPoint = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation())));
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
function TestBox() {
|
||||||
|
this.entity = Entities.addEntity({ type: "Box",
|
||||||
|
position: spawnPoint,
|
||||||
|
dimentions: { x: 1, y: 1, z: 1 },
|
||||||
|
color: { red: 100, green: 100, blue: 255 },
|
||||||
|
gravity: { x: 0, y: 0, z: 0 },
|
||||||
|
visible: true,
|
||||||
|
locked: false,
|
||||||
|
lifetime: 6000 });
|
||||||
|
var self = this;
|
||||||
|
this.timer = Script.setInterval(function () {
|
||||||
|
var colorProp = { color: { red: Math.random() * 255,
|
||||||
|
green: Math.random() * 255,
|
||||||
|
blue: Math.random() * 255 } };
|
||||||
|
Entities.editEntity(self.entity, colorProp);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBox.prototype.Destroy = function () {
|
||||||
|
Script.clearInterval(this.timer);
|
||||||
|
Entities.editEntity(this.entity, { locked: false });
|
||||||
|
Entities.deleteEntity(this.entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
function TestFx(color, emitDirection, emitRate, emitStrength, blinkRate) {
|
||||||
|
var animationSettings = JSON.stringify({ fps: 30,
|
||||||
|
frameIndex: 0,
|
||||||
|
running: true,
|
||||||
|
firstFrame: 0,
|
||||||
|
lastFrame: 30,
|
||||||
|
loop: true });
|
||||||
|
|
||||||
|
this.entity = Entities.addEntity({ type: "ParticleEffect",
|
||||||
|
animationSettings: animationSettings,
|
||||||
|
position: spawnPoint,
|
||||||
|
textures: "http://www.hyperlogic.org/images/particle.png",
|
||||||
|
emitRate: emitRate,
|
||||||
|
emitStrength: emitStrength,
|
||||||
|
emitDirection: emitDirection,
|
||||||
|
color: color,
|
||||||
|
visible: true,
|
||||||
|
locked: false });
|
||||||
|
|
||||||
|
this.isPlaying = true;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this.timer = Script.setInterval(function () {
|
||||||
|
// flip is playing state
|
||||||
|
self.isPlaying = !self.isPlaying;
|
||||||
|
var animProp = { animationIsPlaying: self.isPlaying };
|
||||||
|
Entities.editEntity(self.entity, animProp);
|
||||||
|
}, (1 / blinkRate) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestFx.prototype.Destroy = function () {
|
||||||
|
Script.clearInterval(this.timer);
|
||||||
|
Entities.editEntity(this.entity, { locked: false });
|
||||||
|
Entities.deleteEntity(this.entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
var objs = [];
|
||||||
|
function Init() {
|
||||||
|
objs.push(new TestBox());
|
||||||
|
objs.push(new TestFx({ red: 255, blue: 0, green: 0 },
|
||||||
|
{ x: 0.5, y: 1.0, z: 0.0 },
|
||||||
|
100, 3, 1));
|
||||||
|
objs.push(new TestFx({ red: 0, blue: 255, green: 0 },
|
||||||
|
{ x: 0, y: 1, z: 0 },
|
||||||
|
1000, 5, 0.5));
|
||||||
|
objs.push(new TestFx({ red: 0, blue: 0, green: 255 },
|
||||||
|
{ x: -0.5, y: 1, z: 0 },
|
||||||
|
100, 3, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShutDown() {
|
||||||
|
var i, len = objs.length;
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
objs[i].Destroy();
|
||||||
|
}
|
||||||
|
objs = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Init();
|
||||||
|
Script.scriptEnding.connect(ShutDown);
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ Script.include([
|
||||||
"libraries/gridTool.js",
|
"libraries/gridTool.js",
|
||||||
"libraries/entityList.js",
|
"libraries/entityList.js",
|
||||||
"libraries/lightOverlayManager.js",
|
"libraries/lightOverlayManager.js",
|
||||||
"libraries/zoneOverlayManager.js",
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var selectionDisplay = SelectionDisplay;
|
var selectionDisplay = SelectionDisplay;
|
||||||
|
@ -36,7 +35,6 @@ var selectionManager = SelectionManager;
|
||||||
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
||||||
|
|
||||||
var lightOverlayManager = new LightOverlayManager();
|
var lightOverlayManager = new LightOverlayManager();
|
||||||
var zoneOverlayManager = new ZoneOverlayManager();
|
|
||||||
|
|
||||||
var cameraManager = new CameraManager();
|
var cameraManager = new CameraManager();
|
||||||
|
|
||||||
|
@ -49,7 +47,6 @@ var entityListTool = EntityListTool();
|
||||||
selectionManager.addEventListener(function() {
|
selectionManager.addEventListener(function() {
|
||||||
selectionDisplay.updateHandles();
|
selectionDisplay.updateHandles();
|
||||||
lightOverlayManager.updatePositions();
|
lightOverlayManager.updatePositions();
|
||||||
zoneOverlayManager.updatePositions();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var windowDimensions = Controller.getViewportDimensions();
|
var windowDimensions = Controller.getViewportDimensions();
|
||||||
|
@ -246,7 +243,7 @@ var toolBar = (function () {
|
||||||
}
|
}
|
||||||
toolBar.selectTool(activeButton, isActive);
|
toolBar.selectTool(activeButton, isActive);
|
||||||
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
||||||
zoneOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets visibility of tool buttons, excluding the power button
|
// Sets visibility of tool buttons, excluding the power button
|
||||||
|
@ -1000,7 +997,7 @@ function handeMenuEvent(menuItem) {
|
||||||
} else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
|
} else if (menuItem == MENU_SHOW_LIGHTS_IN_EDIT_MODE) {
|
||||||
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
lightOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_IN_EDIT_MODE));
|
||||||
} else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
} else if (menuItem == MENU_SHOW_ZONES_IN_EDIT_MODE) {
|
||||||
zoneOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE));
|
||||||
}
|
}
|
||||||
tooltip.show(false);
|
tooltip.show(false);
|
||||||
}
|
}
|
||||||
|
@ -1030,8 +1027,11 @@ function importSVO(importURL) {
|
||||||
var success = Clipboard.importEntities(importURL);
|
var success = Clipboard.importEntities(importURL);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
var position = getPositionToCreateEntity();
|
var VERY_LARGE = 10000;
|
||||||
|
var position = { x: 0, y: 0, z: 0};
|
||||||
|
if (Clipboard.getClipboardContentsLargestDimension() < VERY_LARGE) {
|
||||||
|
position = getPositionToCreateEntity();
|
||||||
|
}
|
||||||
var pastedEntityIDs = Clipboard.pasteEntities(position);
|
var pastedEntityIDs = Clipboard.pasteEntities(position);
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
|
@ -1295,6 +1295,25 @@ PropertiesTool = function(opts) {
|
||||||
pushCommandForSelections();
|
pushCommandForSelections();
|
||||||
selectionManager._update();
|
selectionManager._update();
|
||||||
}
|
}
|
||||||
|
} else if (data.action == "centerAtmosphereToZone") {
|
||||||
|
if (selectionManager.hasSelection()) {
|
||||||
|
selectionManager.saveProperties();
|
||||||
|
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||||
|
var properties = selectionManager.savedProperties[selectionManager.selections[i].id];
|
||||||
|
if (properties.type == "Zone") {
|
||||||
|
var centerOfZone = properties.boundingBox.center;
|
||||||
|
var atmosphereCenter = { x: centerOfZone.x,
|
||||||
|
y: centerOfZone.y - properties.atmosphere.innerRadius,
|
||||||
|
z: centerOfZone.z };
|
||||||
|
|
||||||
|
Entities.editEntity(selectionManager.selections[i], {
|
||||||
|
atmosphere: { center: atmosphereCenter },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pushCommandForSelections();
|
||||||
|
selectionManager._update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
520
examples/html/colpick.js
Normal file
520
examples/html/colpick.js
Normal file
|
@ -0,0 +1,520 @@
|
||||||
|
/*
|
||||||
|
colpick Color Picker
|
||||||
|
Copyright 2013 Jose Vargas. Licensed under GPL license. Based on Stefan Petre's Color Picker www.eyecon.ro, dual licensed under the MIT and GPL licenses
|
||||||
|
|
||||||
|
For usage and examples: colpick.com/plugin
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
var colpick = function () {
|
||||||
|
var
|
||||||
|
tpl = '<div class="colpick"><div class="colpick_color"><div class="colpick_color_overlay1"><div class="colpick_color_overlay2"><div class="colpick_selector_outer"><div class="colpick_selector_inner"></div></div></div></div></div><div class="colpick_hue"><div class="colpick_hue_arrs"><div class="colpick_hue_larr"></div><div class="colpick_hue_rarr"></div></div></div><div class="colpick_new_color"></div><div class="colpick_current_color"></div><div class="colpick_hex_field"><div class="colpick_field_letter">#</div><input type="text" maxlength="6" size="6" /></div><div class="colpick_rgb_r colpick_field"><div class="colpick_field_letter">R</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_rgb_g colpick_field"><div class="colpick_field_letter">G</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_rgb_b colpick_field"><div class="colpick_field_letter">B</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_hsb_h colpick_field"><div class="colpick_field_letter">H</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_hsb_s colpick_field"><div class="colpick_field_letter">S</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_hsb_b colpick_field"><div class="colpick_field_letter">B</div><input type="text" maxlength="3" size="3" /><div class="colpick_field_arrs"><div class="colpick_field_uarr"></div><div class="colpick_field_darr"></div></div></div><div class="colpick_submit"></div></div>',
|
||||||
|
defaults = {
|
||||||
|
showEvent: 'click',
|
||||||
|
onShow: function () {},
|
||||||
|
onBeforeShow: function(){},
|
||||||
|
onHide: function () {},
|
||||||
|
onChange: function () {},
|
||||||
|
onSubmit: function () {},
|
||||||
|
colorScheme: 'light',
|
||||||
|
color: '3289c7',
|
||||||
|
livePreview: true,
|
||||||
|
flat: false,
|
||||||
|
layout: 'full',
|
||||||
|
submit: 1,
|
||||||
|
submitText: 'OK',
|
||||||
|
height: 156
|
||||||
|
},
|
||||||
|
//Fill the inputs of the plugin
|
||||||
|
fillRGBFields = function (hsb, cal) {
|
||||||
|
var rgb = hsbToRgb(hsb);
|
||||||
|
$(cal).data('colpick').fields
|
||||||
|
.eq(1).val(rgb.r).end()
|
||||||
|
.eq(2).val(rgb.g).end()
|
||||||
|
.eq(3).val(rgb.b).end();
|
||||||
|
},
|
||||||
|
fillHSBFields = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').fields
|
||||||
|
.eq(4).val(Math.round(hsb.h)).end()
|
||||||
|
.eq(5).val(Math.round(hsb.s)).end()
|
||||||
|
.eq(6).val(Math.round(hsb.b)).end();
|
||||||
|
},
|
||||||
|
fillHexFields = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').fields.eq(0).val(hsbToHex(hsb));
|
||||||
|
},
|
||||||
|
//Set the round selector position
|
||||||
|
setSelector = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').selector.css('backgroundColor', '#' + hsbToHex({h: hsb.h, s: 100, b: 100}));
|
||||||
|
$(cal).data('colpick').selectorIndic.css({
|
||||||
|
left: parseInt($(cal).data('colpick').height * hsb.s/100, 10),
|
||||||
|
top: parseInt($(cal).data('colpick').height * (100-hsb.b)/100, 10)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//Set the hue selector position
|
||||||
|
setHue = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').hue.css('top', parseInt($(cal).data('colpick').height - $(cal).data('colpick').height * hsb.h/360, 10));
|
||||||
|
},
|
||||||
|
//Set current and new colors
|
||||||
|
setCurrentColor = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').currentColor.css('backgroundColor', '#' + hsbToHex(hsb));
|
||||||
|
},
|
||||||
|
setNewColor = function (hsb, cal) {
|
||||||
|
$(cal).data('colpick').newColor.css('backgroundColor', '#' + hsbToHex(hsb));
|
||||||
|
},
|
||||||
|
//Called when the new color is changed
|
||||||
|
change = function (ev) {
|
||||||
|
var cal = $(this).parent().parent(), col;
|
||||||
|
if (this.parentNode.className.indexOf('_hex') > 0) {
|
||||||
|
cal.data('colpick').color = col = hexToHsb(fixHex(this.value));
|
||||||
|
fillRGBFields(col, cal.get(0));
|
||||||
|
fillHSBFields(col, cal.get(0));
|
||||||
|
} else if (this.parentNode.className.indexOf('_hsb') > 0) {
|
||||||
|
cal.data('colpick').color = col = fixHSB({
|
||||||
|
h: parseInt(cal.data('colpick').fields.eq(4).val(), 10),
|
||||||
|
s: parseInt(cal.data('colpick').fields.eq(5).val(), 10),
|
||||||
|
b: parseInt(cal.data('colpick').fields.eq(6).val(), 10)
|
||||||
|
});
|
||||||
|
fillRGBFields(col, cal.get(0));
|
||||||
|
fillHexFields(col, cal.get(0));
|
||||||
|
} else {
|
||||||
|
cal.data('colpick').color = col = rgbToHsb(fixRGB({
|
||||||
|
r: parseInt(cal.data('colpick').fields.eq(1).val(), 10),
|
||||||
|
g: parseInt(cal.data('colpick').fields.eq(2).val(), 10),
|
||||||
|
b: parseInt(cal.data('colpick').fields.eq(3).val(), 10)
|
||||||
|
}));
|
||||||
|
fillHexFields(col, cal.get(0));
|
||||||
|
fillHSBFields(col, cal.get(0));
|
||||||
|
}
|
||||||
|
setSelector(col, cal.get(0));
|
||||||
|
setHue(col, cal.get(0));
|
||||||
|
setNewColor(col, cal.get(0));
|
||||||
|
cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 0]);
|
||||||
|
},
|
||||||
|
//Change style on blur and on focus of inputs
|
||||||
|
blur = function (ev) {
|
||||||
|
$(this).parent().removeClass('colpick_focus');
|
||||||
|
},
|
||||||
|
focus = function () {
|
||||||
|
$(this).parent().parent().data('colpick').fields.parent().removeClass('colpick_focus');
|
||||||
|
$(this).parent().addClass('colpick_focus');
|
||||||
|
},
|
||||||
|
//Increment/decrement arrows functions
|
||||||
|
downIncrement = function (ev) {
|
||||||
|
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
|
||||||
|
var field = $(this).parent().find('input').focus();
|
||||||
|
var current = {
|
||||||
|
el: $(this).parent().addClass('colpick_slider'),
|
||||||
|
max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
|
||||||
|
y: ev.pageY,
|
||||||
|
field: field,
|
||||||
|
val: parseInt(field.val(), 10),
|
||||||
|
preview: $(this).parent().parent().data('colpick').livePreview
|
||||||
|
};
|
||||||
|
$(document).mouseup(current, upIncrement);
|
||||||
|
$(document).mousemove(current, moveIncrement);
|
||||||
|
},
|
||||||
|
moveIncrement = function (ev) {
|
||||||
|
ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val - ev.pageY + ev.data.y, 10))));
|
||||||
|
if (ev.data.preview) {
|
||||||
|
change.apply(ev.data.field.get(0), [true]);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
upIncrement = function (ev) {
|
||||||
|
change.apply(ev.data.field.get(0), [true]);
|
||||||
|
ev.data.el.removeClass('colpick_slider').find('input').focus();
|
||||||
|
$(document).off('mouseup', upIncrement);
|
||||||
|
$(document).off('mousemove', moveIncrement);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
//Hue slider functions
|
||||||
|
downHue = function (ev) {
|
||||||
|
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
|
||||||
|
var current = {
|
||||||
|
cal: $(this).parent(),
|
||||||
|
y: $(this).offset().top
|
||||||
|
};
|
||||||
|
$(document).on('mouseup touchend',current,upHue);
|
||||||
|
$(document).on('mousemove touchmove',current,moveHue);
|
||||||
|
|
||||||
|
var pageY = ((ev.type == 'touchstart') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY );
|
||||||
|
change.apply(
|
||||||
|
current.cal.data('colpick')
|
||||||
|
.fields.eq(4).val(parseInt(360*(current.cal.data('colpick').height - (pageY - current.y))/current.cal.data('colpick').height, 10))
|
||||||
|
.get(0),
|
||||||
|
[current.cal.data('colpick').livePreview]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
moveHue = function (ev) {
|
||||||
|
var pageY = ((ev.type == 'touchmove') ? ev.originalEvent.changedTouches[0].pageY : ev.pageY );
|
||||||
|
change.apply(
|
||||||
|
ev.data.cal.data('colpick')
|
||||||
|
.fields.eq(4).val(parseInt(360*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.y))))/ev.data.cal.data('colpick').height, 10))
|
||||||
|
.get(0),
|
||||||
|
[ev.data.preview]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
upHue = function (ev) {
|
||||||
|
fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0));
|
||||||
|
fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0));
|
||||||
|
$(document).off('mouseup touchend',upHue);
|
||||||
|
$(document).off('mousemove touchmove',moveHue);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
//Color selector functions
|
||||||
|
downSelector = function (ev) {
|
||||||
|
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
|
||||||
|
var current = {
|
||||||
|
cal: $(this).parent(),
|
||||||
|
pos: $(this).offset()
|
||||||
|
};
|
||||||
|
current.preview = current.cal.data('colpick').livePreview;
|
||||||
|
|
||||||
|
$(document).on('mouseup touchend',current,upSelector);
|
||||||
|
$(document).on('mousemove touchmove',current,moveSelector);
|
||||||
|
|
||||||
|
var payeX,pageY;
|
||||||
|
if(ev.type == 'touchstart') {
|
||||||
|
pageX = ev.originalEvent.changedTouches[0].pageX,
|
||||||
|
pageY = ev.originalEvent.changedTouches[0].pageY;
|
||||||
|
} else {
|
||||||
|
pageX = ev.pageX;
|
||||||
|
pageY = ev.pageY;
|
||||||
|
}
|
||||||
|
|
||||||
|
change.apply(
|
||||||
|
current.cal.data('colpick').fields
|
||||||
|
.eq(6).val(parseInt(100*(current.cal.data('colpick').height - (pageY - current.pos.top))/current.cal.data('colpick').height, 10)).end()
|
||||||
|
.eq(5).val(parseInt(100*(pageX - current.pos.left)/current.cal.data('colpick').height, 10))
|
||||||
|
.get(0),
|
||||||
|
[current.preview]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
moveSelector = function (ev) {
|
||||||
|
var payeX,pageY;
|
||||||
|
if(ev.type == 'touchmove') {
|
||||||
|
pageX = ev.originalEvent.changedTouches[0].pageX,
|
||||||
|
pageY = ev.originalEvent.changedTouches[0].pageY;
|
||||||
|
} else {
|
||||||
|
pageX = ev.pageX;
|
||||||
|
pageY = ev.pageY;
|
||||||
|
}
|
||||||
|
|
||||||
|
change.apply(
|
||||||
|
ev.data.cal.data('colpick').fields
|
||||||
|
.eq(6).val(parseInt(100*(ev.data.cal.data('colpick').height - Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageY - ev.data.pos.top))))/ev.data.cal.data('colpick').height, 10)).end()
|
||||||
|
.eq(5).val(parseInt(100*(Math.max(0,Math.min(ev.data.cal.data('colpick').height,(pageX - ev.data.pos.left))))/ev.data.cal.data('colpick').height, 10))
|
||||||
|
.get(0),
|
||||||
|
[ev.data.preview]
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
upSelector = function (ev) {
|
||||||
|
fillRGBFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0));
|
||||||
|
fillHexFields(ev.data.cal.data('colpick').color, ev.data.cal.get(0));
|
||||||
|
$(document).off('mouseup touchend',upSelector);
|
||||||
|
$(document).off('mousemove touchmove',moveSelector);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
//Submit button
|
||||||
|
clickSubmit = function (ev) {
|
||||||
|
var cal = $(this).parent();
|
||||||
|
var col = cal.data('colpick').color;
|
||||||
|
cal.data('colpick').origColor = col;
|
||||||
|
setCurrentColor(col, cal.get(0));
|
||||||
|
cal.data('colpick').onSubmit(col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el);
|
||||||
|
},
|
||||||
|
//Show/hide the color picker
|
||||||
|
show = function (ev) {
|
||||||
|
// Prevent the trigger of any direct parent
|
||||||
|
ev.stopPropagation();
|
||||||
|
var cal = $('#' + $(this).data('colpickId'));
|
||||||
|
cal.data('colpick').onBeforeShow.apply(this, [cal.get(0)]);
|
||||||
|
var pos = $(this).offset();
|
||||||
|
var top = pos.top + this.offsetHeight;
|
||||||
|
var left = pos.left;
|
||||||
|
var viewPort = getViewport();
|
||||||
|
var calW = cal.width();
|
||||||
|
if (left + calW > viewPort.l + viewPort.w) {
|
||||||
|
left -= calW;
|
||||||
|
}
|
||||||
|
cal.css({left: left + 'px', top: top + 'px'});
|
||||||
|
if (cal.data('colpick').onShow.apply(this, [cal.get(0)]) != false) {
|
||||||
|
cal.show();
|
||||||
|
}
|
||||||
|
//Hide when user clicks outside
|
||||||
|
$('html').mousedown({cal:cal}, hide);
|
||||||
|
cal.mousedown(function(ev){ev.stopPropagation();})
|
||||||
|
},
|
||||||
|
hide = function (ev) {
|
||||||
|
if (ev.data.cal.data('colpick').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
|
||||||
|
ev.data.cal.hide();
|
||||||
|
}
|
||||||
|
$('html').off('mousedown', hide);
|
||||||
|
},
|
||||||
|
getViewport = function () {
|
||||||
|
var m = document.compatMode == 'CSS1Compat';
|
||||||
|
return {
|
||||||
|
l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
|
||||||
|
w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
//Fix the values if the user enters a negative or high value
|
||||||
|
fixHSB = function (hsb) {
|
||||||
|
return {
|
||||||
|
h: Math.min(360, Math.max(0, hsb.h)),
|
||||||
|
s: Math.min(100, Math.max(0, hsb.s)),
|
||||||
|
b: Math.min(100, Math.max(0, hsb.b))
|
||||||
|
};
|
||||||
|
},
|
||||||
|
fixRGB = function (rgb) {
|
||||||
|
return {
|
||||||
|
r: Math.min(255, Math.max(0, rgb.r)),
|
||||||
|
g: Math.min(255, Math.max(0, rgb.g)),
|
||||||
|
b: Math.min(255, Math.max(0, rgb.b))
|
||||||
|
};
|
||||||
|
},
|
||||||
|
fixHex = function (hex) {
|
||||||
|
var len = 6 - hex.length;
|
||||||
|
if (len > 0) {
|
||||||
|
var o = [];
|
||||||
|
for (var i=0; i<len; i++) {
|
||||||
|
o.push('0');
|
||||||
|
}
|
||||||
|
o.push(hex);
|
||||||
|
hex = o.join('');
|
||||||
|
}
|
||||||
|
return hex;
|
||||||
|
},
|
||||||
|
restoreOriginal = function () {
|
||||||
|
var cal = $(this).parent();
|
||||||
|
var col = cal.data('colpick').origColor;
|
||||||
|
cal.data('colpick').color = col;
|
||||||
|
fillRGBFields(col, cal.get(0));
|
||||||
|
fillHexFields(col, cal.get(0));
|
||||||
|
fillHSBFields(col, cal.get(0));
|
||||||
|
setSelector(col, cal.get(0));
|
||||||
|
setHue(col, cal.get(0));
|
||||||
|
setNewColor(col, cal.get(0));
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
init: function (opt) {
|
||||||
|
opt = $.extend({}, defaults, opt||{});
|
||||||
|
//Set color
|
||||||
|
if (typeof opt.color == 'string') {
|
||||||
|
opt.color = hexToHsb(opt.color);
|
||||||
|
} else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {
|
||||||
|
opt.color = rgbToHsb(opt.color);
|
||||||
|
} else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {
|
||||||
|
opt.color = fixHSB(opt.color);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//For each selected DOM element
|
||||||
|
return this.each(function () {
|
||||||
|
//If the element does not have an ID
|
||||||
|
if (!$(this).data('colpickId')) {
|
||||||
|
var options = $.extend({}, opt);
|
||||||
|
options.origColor = opt.color;
|
||||||
|
//Generate and assign a random ID
|
||||||
|
var id = 'collorpicker_' + parseInt(Math.random() * 1000);
|
||||||
|
$(this).data('colpickId', id);
|
||||||
|
//Set the tpl's ID and get the HTML
|
||||||
|
var cal = $(tpl).attr('id', id);
|
||||||
|
//Add class according to layout
|
||||||
|
cal.addClass('colpick_'+options.layout+(options.submit?'':' colpick_'+options.layout+'_ns'));
|
||||||
|
//Add class if the color scheme is not default
|
||||||
|
if(options.colorScheme != 'light') {
|
||||||
|
cal.addClass('colpick_'+options.colorScheme);
|
||||||
|
}
|
||||||
|
//Setup submit button
|
||||||
|
cal.find('div.colpick_submit').html(options.submitText).click(clickSubmit);
|
||||||
|
//Setup input fields
|
||||||
|
options.fields = cal.find('input').change(change).blur(blur).focus(focus);
|
||||||
|
cal.find('div.colpick_field_arrs').mousedown(downIncrement).end().find('div.colpick_current_color').click(restoreOriginal);
|
||||||
|
//Setup hue selector
|
||||||
|
options.selector = cal.find('div.colpick_color').on('mousedown touchstart',downSelector);
|
||||||
|
options.selectorIndic = options.selector.find('div.colpick_selector_outer');
|
||||||
|
//Store parts of the plugin
|
||||||
|
options.el = this;
|
||||||
|
options.hue = cal.find('div.colpick_hue_arrs');
|
||||||
|
huebar = options.hue.parent();
|
||||||
|
//Paint the hue bar
|
||||||
|
var UA = navigator.userAgent.toLowerCase();
|
||||||
|
var isIE = navigator.appName === 'Microsoft Internet Explorer';
|
||||||
|
var IEver = isIE ? parseFloat( UA.match( /msie ([0-9]{1,}[\.0-9]{0,})/ )[1] ) : 0;
|
||||||
|
var ngIE = ( isIE && IEver < 10 );
|
||||||
|
var stops = ['#ff0000','#ff0080','#ff00ff','#8000ff','#0000ff','#0080ff','#00ffff','#00ff80','#00ff00','#80ff00','#ffff00','#ff8000','#ff0000'];
|
||||||
|
if(ngIE) {
|
||||||
|
var i, div;
|
||||||
|
for(i=0; i<=11; i++) {
|
||||||
|
div = $('<div></div>').attr('style','height:8.333333%; filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='+stops[i]+', endColorstr='+stops[i+1]+')";');
|
||||||
|
huebar.append(div);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stopList = stops.join(',');
|
||||||
|
huebar.attr('style','background:-webkit-linear-gradient(top,'+stopList+'); background: -o-linear-gradient(top,'+stopList+'); background: -ms-linear-gradient(top,'+stopList+'); background:-moz-linear-gradient(top,'+stopList+'); -webkit-linear-gradient(top,'+stopList+'); background:linear-gradient(to bottom,'+stopList+'); ');
|
||||||
|
}
|
||||||
|
cal.find('div.colpick_hue').on('mousedown touchstart',downHue);
|
||||||
|
options.newColor = cal.find('div.colpick_new_color');
|
||||||
|
options.currentColor = cal.find('div.colpick_current_color');
|
||||||
|
//Store options and fill with default color
|
||||||
|
cal.data('colpick', options);
|
||||||
|
fillRGBFields(options.color, cal.get(0));
|
||||||
|
fillHSBFields(options.color, cal.get(0));
|
||||||
|
fillHexFields(options.color, cal.get(0));
|
||||||
|
setHue(options.color, cal.get(0));
|
||||||
|
setSelector(options.color, cal.get(0));
|
||||||
|
setCurrentColor(options.color, cal.get(0));
|
||||||
|
setNewColor(options.color, cal.get(0));
|
||||||
|
//Append to body if flat=false, else show in place
|
||||||
|
if (options.flat) {
|
||||||
|
cal.appendTo(this).show();
|
||||||
|
cal.css({
|
||||||
|
position: 'relative',
|
||||||
|
display: 'block'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
cal.appendTo(document.body);
|
||||||
|
$(this).on(options.showEvent, show);
|
||||||
|
cal.css({
|
||||||
|
position:'absolute'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//Shows the picker
|
||||||
|
showPicker: function() {
|
||||||
|
return this.each( function () {
|
||||||
|
if ($(this).data('colpickId')) {
|
||||||
|
show.apply(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//Hides the picker
|
||||||
|
hidePicker: function() {
|
||||||
|
return this.each( function () {
|
||||||
|
if ($(this).data('colpickId')) {
|
||||||
|
$('#' + $(this).data('colpickId')).hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//Sets a color as new and current (default)
|
||||||
|
setColor: function(col, setCurrent) {
|
||||||
|
setCurrent = (typeof setCurrent === "undefined") ? 1 : setCurrent;
|
||||||
|
if (typeof col == 'string') {
|
||||||
|
col = hexToHsb(col);
|
||||||
|
} else if (col.r != undefined && col.g != undefined && col.b != undefined) {
|
||||||
|
col = rgbToHsb(col);
|
||||||
|
} else if (col.h != undefined && col.s != undefined && col.b != undefined) {
|
||||||
|
col = fixHSB(col);
|
||||||
|
} else {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return this.each(function(){
|
||||||
|
if ($(this).data('colpickId')) {
|
||||||
|
var cal = $('#' + $(this).data('colpickId'));
|
||||||
|
cal.data('colpick').color = col;
|
||||||
|
cal.data('colpick').origColor = col;
|
||||||
|
fillRGBFields(col, cal.get(0));
|
||||||
|
fillHSBFields(col, cal.get(0));
|
||||||
|
fillHexFields(col, cal.get(0));
|
||||||
|
setHue(col, cal.get(0));
|
||||||
|
setSelector(col, cal.get(0));
|
||||||
|
|
||||||
|
setNewColor(col, cal.get(0));
|
||||||
|
cal.data('colpick').onChange.apply(cal.parent(), [col, hsbToHex(col), hsbToRgb(col), cal.data('colpick').el, 1]);
|
||||||
|
if(setCurrent) {
|
||||||
|
setCurrentColor(col, cal.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
//Color space convertions
|
||||||
|
var hexToRgb = function (hex) {
|
||||||
|
var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
|
||||||
|
return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
|
||||||
|
};
|
||||||
|
var hexToHsb = function (hex) {
|
||||||
|
return rgbToHsb(hexToRgb(hex));
|
||||||
|
};
|
||||||
|
var rgbToHsb = function (rgb) {
|
||||||
|
var hsb = {h: 0, s: 0, b: 0};
|
||||||
|
var min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||||
|
var max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||||
|
var delta = max - min;
|
||||||
|
hsb.b = max;
|
||||||
|
hsb.s = max != 0 ? 255 * delta / max : 0;
|
||||||
|
if (hsb.s != 0) {
|
||||||
|
if (rgb.r == max) hsb.h = (rgb.g - rgb.b) / delta;
|
||||||
|
else if (rgb.g == max) hsb.h = 2 + (rgb.b - rgb.r) / delta;
|
||||||
|
else hsb.h = 4 + (rgb.r - rgb.g) / delta;
|
||||||
|
} else hsb.h = -1;
|
||||||
|
hsb.h *= 60;
|
||||||
|
if (hsb.h < 0) hsb.h += 360;
|
||||||
|
hsb.s *= 100/255;
|
||||||
|
hsb.b *= 100/255;
|
||||||
|
return hsb;
|
||||||
|
};
|
||||||
|
var hsbToRgb = function (hsb) {
|
||||||
|
var rgb = {};
|
||||||
|
var h = hsb.h;
|
||||||
|
var s = hsb.s*255/100;
|
||||||
|
var v = hsb.b*255/100;
|
||||||
|
if(s == 0) {
|
||||||
|
rgb.r = rgb.g = rgb.b = v;
|
||||||
|
} else {
|
||||||
|
var t1 = v;
|
||||||
|
var t2 = (255-s)*v/255;
|
||||||
|
var t3 = (t1-t2)*(h%60)/60;
|
||||||
|
if(h==360) h = 0;
|
||||||
|
if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3}
|
||||||
|
else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3}
|
||||||
|
else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3}
|
||||||
|
else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3}
|
||||||
|
else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3}
|
||||||
|
else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3}
|
||||||
|
else {rgb.r=0; rgb.g=0; rgb.b=0}
|
||||||
|
}
|
||||||
|
return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
|
||||||
|
};
|
||||||
|
var rgbToHex = function (rgb) {
|
||||||
|
var hex = [
|
||||||
|
rgb.r.toString(16),
|
||||||
|
rgb.g.toString(16),
|
||||||
|
rgb.b.toString(16)
|
||||||
|
];
|
||||||
|
$.each(hex, function (nr, val) {
|
||||||
|
if (val.length == 1) {
|
||||||
|
hex[nr] = '0' + val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return hex.join('');
|
||||||
|
};
|
||||||
|
var hsbToHex = function (hsb) {
|
||||||
|
return rgbToHex(hsbToRgb(hsb));
|
||||||
|
};
|
||||||
|
$.fn.extend({
|
||||||
|
colpick: colpick.init,
|
||||||
|
colpickHide: colpick.hidePicker,
|
||||||
|
colpickShow: colpick.showPicker,
|
||||||
|
colpickSetColor: colpick.setColor
|
||||||
|
});
|
||||||
|
$.extend({
|
||||||
|
colpick:{
|
||||||
|
rgbToHex: rgbToHex,
|
||||||
|
rgbToHsb: rgbToHsb,
|
||||||
|
hsbToHex: hsbToHex,
|
||||||
|
hsbToRgb: hsbToRgb,
|
||||||
|
hexToHsb: hexToHsb,
|
||||||
|
hexToRgb: hexToRgb
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})(jQuery);
|
420
examples/html/css/colpick.css
Normal file
420
examples/html/css/colpick.css
Normal file
|
@ -0,0 +1,420 @@
|
||||||
|
/*
|
||||||
|
colpick Color Picker / colpick.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Main container*/
|
||||||
|
.colpick {
|
||||||
|
position: absolute;
|
||||||
|
width: 346px;
|
||||||
|
height: 170px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: none;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
background:#ebebeb;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
/*Prevents selecting text when dragging the selectors*/
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
-o-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/*Color selection box with gradients*/
|
||||||
|
.colpick_color {
|
||||||
|
position: absolute;
|
||||||
|
left: 7px;
|
||||||
|
top: 7px;
|
||||||
|
width: 156px;
|
||||||
|
height: 156px;
|
||||||
|
overflow: hidden;
|
||||||
|
outline: 1px solid #aaa;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.colpick_color_overlay1 {
|
||||||
|
position: absolute;
|
||||||
|
left:0;
|
||||||
|
top:0;
|
||||||
|
width: 156px;
|
||||||
|
height: 156px;
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff')"; /* IE8 */
|
||||||
|
background: -moz-linear-gradient(left, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%); /* FF3.6+ */
|
||||||
|
background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
|
||||||
|
background: -webkit-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */
|
||||||
|
background: -o-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* Opera 11.10+ */
|
||||||
|
background: -ms-linear-gradient(left, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%); /* IE10+ */
|
||||||
|
background: linear-gradient(to right, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100%);
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1,startColorstr='#ffffff', endColorstr='#00ffffff'); /* IE6 & IE7 */
|
||||||
|
}
|
||||||
|
.colpick_color_overlay2 {
|
||||||
|
position: absolute;
|
||||||
|
left:0;
|
||||||
|
top:0;
|
||||||
|
width: 156px;
|
||||||
|
height: 156px;
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#00000000', endColorstr='#000000')"; /* IE8 */
|
||||||
|
background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */
|
||||||
|
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */
|
||||||
|
background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */
|
||||||
|
background: -o-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* Opera 11.10+ */
|
||||||
|
background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* IE10+ */
|
||||||
|
background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,1) 100%); /* W3C */
|
||||||
|
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00000000', endColorstr='#000000',GradientType=0 ); /* IE6-9 */
|
||||||
|
}
|
||||||
|
/*Circular color selector*/
|
||||||
|
.colpick_selector_outer {
|
||||||
|
background:none;
|
||||||
|
position: absolute;
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
margin: -6px 0 0 -6px;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.colpick_selector_inner{
|
||||||
|
position: absolute;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
border: 1px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
/*Vertical hue bar*/
|
||||||
|
.colpick_hue {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
left: 175px;
|
||||||
|
width: 19px;
|
||||||
|
height: 156px;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
cursor: n-resize;
|
||||||
|
}
|
||||||
|
/*Hue bar sliding indicator*/
|
||||||
|
.colpick_hue_arrs {
|
||||||
|
position: absolute;
|
||||||
|
left: -8px;
|
||||||
|
width: 35px;
|
||||||
|
height: 7px;
|
||||||
|
margin: -7px 0 0 0;
|
||||||
|
}
|
||||||
|
.colpick_hue_larr {
|
||||||
|
position:absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-top: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid transparent;
|
||||||
|
border-left: 7px solid #858585;
|
||||||
|
}
|
||||||
|
.colpick_hue_rarr {
|
||||||
|
position:absolute;
|
||||||
|
right:0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-top: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid transparent;
|
||||||
|
border-right: 7px solid #858585;
|
||||||
|
}
|
||||||
|
/*New color box*/
|
||||||
|
.colpick_new_color {
|
||||||
|
position: absolute;
|
||||||
|
left: 207px;
|
||||||
|
top: 6px;
|
||||||
|
width: 60px;
|
||||||
|
height: 27px;
|
||||||
|
background: #f00;
|
||||||
|
border: 1px solid #8f8f8f;
|
||||||
|
}
|
||||||
|
/*Current color box*/
|
||||||
|
.colpick_current_color {
|
||||||
|
position: absolute;
|
||||||
|
left: 277px;
|
||||||
|
top: 6px;
|
||||||
|
width: 60px;
|
||||||
|
height: 27px;
|
||||||
|
background: #f00;
|
||||||
|
border: 1px solid #8f8f8f;
|
||||||
|
}
|
||||||
|
/*Input field containers*/
|
||||||
|
.colpick_field, .colpick_hex_field {
|
||||||
|
position: absolute;
|
||||||
|
height: 20px;
|
||||||
|
width: 60px;
|
||||||
|
overflow:hidden;
|
||||||
|
background:#f3f3f3;
|
||||||
|
color:#b8b8b8;
|
||||||
|
font-size:12px;
|
||||||
|
border:1px solid #bdbdbd;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.colpick_rgb_r {
|
||||||
|
top: 40px;
|
||||||
|
left: 207px;
|
||||||
|
}
|
||||||
|
.colpick_rgb_g {
|
||||||
|
top: 67px;
|
||||||
|
left: 207px;
|
||||||
|
}
|
||||||
|
.colpick_rgb_b {
|
||||||
|
top: 94px;
|
||||||
|
left: 207px;
|
||||||
|
}
|
||||||
|
.colpick_hsb_h {
|
||||||
|
top: 40px;
|
||||||
|
left: 277px;
|
||||||
|
}
|
||||||
|
.colpick_hsb_s {
|
||||||
|
top: 67px;
|
||||||
|
left: 277px;
|
||||||
|
}
|
||||||
|
.colpick_hsb_b {
|
||||||
|
top: 94px;
|
||||||
|
left: 277px;
|
||||||
|
}
|
||||||
|
.colpick_hex_field {
|
||||||
|
width: 68px;
|
||||||
|
left: 207px;
|
||||||
|
top: 121px;
|
||||||
|
}
|
||||||
|
/*Text field container on focus*/
|
||||||
|
.colpick_focus {
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
/*Field label container*/
|
||||||
|
.colpick_field_letter {
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
padding-left: 4px;
|
||||||
|
background: #efefef;
|
||||||
|
border-right: 1px solid #bdbdbd;
|
||||||
|
font-weight: bold;
|
||||||
|
color:#777;
|
||||||
|
}
|
||||||
|
/*Text inputs*/
|
||||||
|
.colpick_field input, .colpick_hex_field input {
|
||||||
|
position: absolute;
|
||||||
|
right: 11px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
color: #555;
|
||||||
|
text-align: right;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.colpick_hex_field input {
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
/*Field up/down arrows*/
|
||||||
|
.colpick_field_arrs {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 9px;
|
||||||
|
height: 21px;
|
||||||
|
cursor: n-resize;
|
||||||
|
}
|
||||||
|
.colpick_field_uarr {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
border-bottom: 4px solid #959595;
|
||||||
|
}
|
||||||
|
.colpick_field_darr {
|
||||||
|
position: absolute;
|
||||||
|
bottom:5px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
border-top: 4px solid #959595;
|
||||||
|
}
|
||||||
|
/*Submit/Select button*/
|
||||||
|
.colpick_submit {
|
||||||
|
position: absolute;
|
||||||
|
left: 207px;
|
||||||
|
top: 149px;
|
||||||
|
width: 130px;
|
||||||
|
height: 22px;
|
||||||
|
line-height:22px;
|
||||||
|
background: #efefef;
|
||||||
|
text-align: center;
|
||||||
|
color: #555;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight:bold;
|
||||||
|
border: 1px solid #bdbdbd;
|
||||||
|
-webkit-border-radius: 3px;
|
||||||
|
-moz-border-radius: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.colpick_submit:hover {
|
||||||
|
background:#f3f3f3;
|
||||||
|
border-color:#999;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*full layout with no submit button*/
|
||||||
|
.colpick_full_ns .colpick_submit, .colpick_full_ns .colpick_current_color{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.colpick_full_ns .colpick_new_color {
|
||||||
|
width: 130px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
.colpick_full_ns .colpick_rgb_r, .colpick_full_ns .colpick_hsb_h {
|
||||||
|
top: 42px;
|
||||||
|
}
|
||||||
|
.colpick_full_ns .colpick_rgb_g, .colpick_full_ns .colpick_hsb_s {
|
||||||
|
top: 73px;
|
||||||
|
}
|
||||||
|
.colpick_full_ns .colpick_rgb_b, .colpick_full_ns .colpick_hsb_b {
|
||||||
|
top: 104px;
|
||||||
|
}
|
||||||
|
.colpick_full_ns .colpick_hex_field {
|
||||||
|
top: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*rgbhex layout*/
|
||||||
|
.colpick_rgbhex .colpick_hsb_h, .colpick_rgbhex .colpick_hsb_s, .colpick_rgbhex .colpick_hsb_b {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex {
|
||||||
|
width:282px;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex .colpick_field, .colpick_rgbhex .colpick_submit {
|
||||||
|
width:68px;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex .colpick_new_color {
|
||||||
|
width:34px;
|
||||||
|
border-right:none;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex .colpick_current_color {
|
||||||
|
width:34px;
|
||||||
|
left:240px;
|
||||||
|
border-left:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*rgbhex layout, no submit button*/
|
||||||
|
.colpick_rgbhex_ns .colpick_submit, .colpick_rgbhex_ns .colpick_current_color{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex_ns .colpick_new_color{
|
||||||
|
width:68px;
|
||||||
|
border: 1px solid #8f8f8f;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex_ns .colpick_rgb_r {
|
||||||
|
top: 42px;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex_ns .colpick_rgb_g {
|
||||||
|
top: 73px;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex_ns .colpick_rgb_b {
|
||||||
|
top: 104px;
|
||||||
|
}
|
||||||
|
.colpick_rgbhex_ns .colpick_hex_field {
|
||||||
|
top: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*hex layout*/
|
||||||
|
.colpick_hex .colpick_hsb_h, .colpick_hex .colpick_hsb_s, .colpick_hex .colpick_hsb_b, .colpick_hex .colpick_rgb_r, .colpick_hex .colpick_rgb_g, .colpick_hex .colpick_rgb_b {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.colpick_hex {
|
||||||
|
width:206px;
|
||||||
|
height:201px;
|
||||||
|
}
|
||||||
|
.colpick_hex .colpick_hex_field {
|
||||||
|
width:72px;
|
||||||
|
height:25px;
|
||||||
|
top:168px;
|
||||||
|
left:80px;
|
||||||
|
}
|
||||||
|
.colpick_hex .colpick_hex_field div, .colpick_hex .colpick_hex_field input {
|
||||||
|
height: 25px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
.colpick_hex .colpick_new_color {
|
||||||
|
left:9px;
|
||||||
|
top:168px;
|
||||||
|
width:30px;
|
||||||
|
border-right:none;
|
||||||
|
}
|
||||||
|
.colpick_hex .colpick_current_color {
|
||||||
|
left:39px;
|
||||||
|
top:168px;
|
||||||
|
width:30px;
|
||||||
|
border-left:none;
|
||||||
|
}
|
||||||
|
.colpick_hex .colpick_submit {
|
||||||
|
left:164px;
|
||||||
|
top: 168px;
|
||||||
|
width:30px;
|
||||||
|
height:25px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*hex layout, no submit button*/
|
||||||
|
.colpick_hex_ns .colpick_submit, .colpick_hex_ns .colpick_current_color {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.colpick_hex_ns .colpick_hex_field {
|
||||||
|
width:80px;
|
||||||
|
}
|
||||||
|
.colpick_hex_ns .colpick_new_color{
|
||||||
|
width:60px;
|
||||||
|
border: 1px solid #8f8f8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Dark color scheme*/
|
||||||
|
.colpick_dark {
|
||||||
|
background: #161616;
|
||||||
|
border-color: #2a2a2a;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_color {
|
||||||
|
outline-color: #333;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_hue {
|
||||||
|
border-color: #555;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_field, .colpick_dark .colpick_hex_field {
|
||||||
|
background: #101010;
|
||||||
|
border-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_field_letter {
|
||||||
|
background: #131313;
|
||||||
|
border-color: #2d2d2d;
|
||||||
|
color: #696969;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_field input, .colpick_dark .colpick_hex_field input {
|
||||||
|
color: #7a7a7a;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_field_uarr {
|
||||||
|
border-bottom-color:#696969;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_field_darr {
|
||||||
|
border-top-color:#696969;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_focus {
|
||||||
|
border-color:#444;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_submit {
|
||||||
|
background: #131313;
|
||||||
|
border-color:#2d2d2d;
|
||||||
|
color:#7a7a7a;
|
||||||
|
}
|
||||||
|
.colpick_dark .colpick_submit:hover {
|
||||||
|
background-color:#101010;
|
||||||
|
border-color:#444;
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/colpick.css">
|
||||||
|
<script src="jquery-2.1.4.min.js"></script>
|
||||||
|
<script src="colpick.js"></script>
|
||||||
<script>
|
<script>
|
||||||
var PI = 3.14159265358979;
|
var PI = 3.14159265358979;
|
||||||
var DEGREES_TO_RADIANS = PI / 180.0;
|
var DEGREES_TO_RADIANS = PI / 180.0;
|
||||||
|
@ -146,20 +149,34 @@
|
||||||
|
|
||||||
function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) {
|
function createEmitColorPropertyUpdateFunction(property, elRed, elGreen, elBlue) {
|
||||||
return function() {
|
return function() {
|
||||||
|
emitColorPropertyUpdate(property, elRed.value, elGreen.value, elBlue.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function emitColorPropertyUpdate(property, red, green, blue, group) {
|
||||||
var data = {
|
var data = {
|
||||||
type: "update",
|
type: "update",
|
||||||
properties: {
|
properties: {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
data.properties[property] = {
|
if (group) {
|
||||||
red: elRed.value,
|
data.properties[group] = { };
|
||||||
green: elGreen.value,
|
data.properties[group][property] = {
|
||||||
blue: elBlue.value,
|
red: red,
|
||||||
};
|
green: green,
|
||||||
|
blue: blue,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
data.properties[property] = {
|
||||||
|
red: red,
|
||||||
|
green: green,
|
||||||
|
blue: blue,
|
||||||
|
};
|
||||||
|
}
|
||||||
EventBridge.emitWebEvent(JSON.stringify(data));
|
EventBridge.emitWebEvent(JSON.stringify(data));
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) {
|
function createEmitGroupColorPropertyUpdateFunction(group, property, elRed, elGreen, elBlue) {
|
||||||
return function() {
|
return function() {
|
||||||
var data = {
|
var data = {
|
||||||
|
@ -232,6 +249,7 @@
|
||||||
var elUserData = document.getElementById("property-user-data");
|
var elUserData = document.getElementById("property-user-data");
|
||||||
|
|
||||||
var elColorSection = document.getElementById("color-section");
|
var elColorSection = document.getElementById("color-section");
|
||||||
|
var elColor = document.getElementById("property-color");
|
||||||
var elColorRed = document.getElementById("property-color-red");
|
var elColorRed = document.getElementById("property-color-red");
|
||||||
var elColorGreen = document.getElementById("property-color-green");
|
var elColorGreen = document.getElementById("property-color-green");
|
||||||
var elColorBlue = document.getElementById("property-color-blue");
|
var elColorBlue = document.getElementById("property-color-blue");
|
||||||
|
@ -239,6 +257,7 @@
|
||||||
var elLightSections = document.querySelectorAll(".light-section");
|
var elLightSections = document.querySelectorAll(".light-section");
|
||||||
allSections.push(elLightSections);
|
allSections.push(elLightSections);
|
||||||
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
||||||
|
var elLightColor = document.getElementById("property-light-color");
|
||||||
var elLightColorRed = document.getElementById("property-light-color-red");
|
var elLightColorRed = document.getElementById("property-light-color-red");
|
||||||
var elLightColorGreen = document.getElementById("property-light-color-green");
|
var elLightColorGreen = document.getElementById("property-light-color-green");
|
||||||
var elLightColorBlue = document.getElementById("property-light-color-blue");
|
var elLightColorBlue = document.getElementById("property-light-color-blue");
|
||||||
|
@ -264,9 +283,11 @@
|
||||||
allSections.push(elTextSections);
|
allSections.push(elTextSections);
|
||||||
var elTextText = document.getElementById("property-text-text");
|
var elTextText = document.getElementById("property-text-text");
|
||||||
var elTextLineHeight = document.getElementById("property-text-line-height");
|
var elTextLineHeight = document.getElementById("property-text-line-height");
|
||||||
|
var elTextTextColor = document.getElementById("property-text-text-color");
|
||||||
var elTextTextColorRed = document.getElementById("property-text-text-color-red");
|
var elTextTextColorRed = document.getElementById("property-text-text-color-red");
|
||||||
var elTextTextColorGreen = document.getElementById("property-text-text-color-green");
|
var elTextTextColorGreen = document.getElementById("property-text-text-color-green");
|
||||||
var elTextTextColorBlue = document.getElementById("property-text-text-color-blue");
|
var elTextTextColorBlue = document.getElementById("property-text-text-color-blue");
|
||||||
|
var elTextBackgroundColor = document.getElementById("property-text-background-color");
|
||||||
var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red");
|
var elTextBackgroundColorRed = document.getElementById("property-text-background-color-red");
|
||||||
var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green");
|
var elTextBackgroundColorGreen = document.getElementById("property-text-background-color-green");
|
||||||
var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue");
|
var elTextBackgroundColorBlue = document.getElementById("property-text-background-color-blue");
|
||||||
|
@ -274,6 +295,7 @@
|
||||||
var elZoneSections = document.querySelectorAll(".zone-section");
|
var elZoneSections = document.querySelectorAll(".zone-section");
|
||||||
allSections.push(elZoneSections);
|
allSections.push(elZoneSections);
|
||||||
var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled");
|
var elZoneStageSunModelEnabled = document.getElementById("property-zone-stage-sun-model-enabled");
|
||||||
|
var elZoneKeyLightColor = document.getElementById("property-zone-key-light-color");
|
||||||
var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red");
|
var elZoneKeyLightColorRed = document.getElementById("property-zone-key-light-color-red");
|
||||||
var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green");
|
var elZoneKeyLightColorGreen = document.getElementById("property-zone-key-light-color-green");
|
||||||
var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue");
|
var elZoneKeyLightColorBlue = document.getElementById("property-zone-key-light-color-blue");
|
||||||
|
@ -292,6 +314,7 @@
|
||||||
|
|
||||||
var elZoneBackgroundMode = document.getElementById("property-zone-background-mode");
|
var elZoneBackgroundMode = document.getElementById("property-zone-background-mode");
|
||||||
|
|
||||||
|
var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color");
|
||||||
var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red");
|
var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red");
|
||||||
var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green");
|
var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green");
|
||||||
var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue");
|
var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue");
|
||||||
|
@ -300,6 +323,8 @@
|
||||||
var elZoneAtmosphereCenterX = document.getElementById("property-zone-atmosphere-center-x");
|
var elZoneAtmosphereCenterX = document.getElementById("property-zone-atmosphere-center-x");
|
||||||
var elZoneAtmosphereCenterY = document.getElementById("property-zone-atmosphere-center-y");
|
var elZoneAtmosphereCenterY = document.getElementById("property-zone-atmosphere-center-y");
|
||||||
var elZoneAtmosphereCenterZ = document.getElementById("property-zone-atmosphere-center-z");
|
var elZoneAtmosphereCenterZ = document.getElementById("property-zone-atmosphere-center-z");
|
||||||
|
var elCenterAtmosphereToZone = document.getElementById("center-atmosphere-in-zone");
|
||||||
|
|
||||||
var elZoneAtmosphereInnerRadius = document.getElementById("property-zone-atmosphere-inner-radius");
|
var elZoneAtmosphereInnerRadius = document.getElementById("property-zone-atmosphere-inner-radius");
|
||||||
var elZoneAtmosphereOuterRadius = document.getElementById("property-zone-atmosphere-outer-radius");
|
var elZoneAtmosphereOuterRadius = document.getElementById("property-zone-atmosphere-outer-radius");
|
||||||
var elZoneAtmosphereMieScattering = document.getElementById("property-zone-atmosphere-mie-scattering");
|
var elZoneAtmosphereMieScattering = document.getElementById("property-zone-atmosphere-mie-scattering");
|
||||||
|
@ -423,6 +448,7 @@
|
||||||
elColorRed.value = properties.color.red;
|
elColorRed.value = properties.color.red;
|
||||||
elColorGreen.value = properties.color.green;
|
elColorGreen.value = properties.color.green;
|
||||||
elColorBlue.value = properties.color.blue;
|
elColorBlue.value = properties.color.blue;
|
||||||
|
elColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
|
||||||
} else {
|
} else {
|
||||||
elColorSection.style.display = 'none';
|
elColorSection.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
@ -449,6 +475,7 @@
|
||||||
|
|
||||||
elTextText.value = properties.text;
|
elTextText.value = properties.text;
|
||||||
elTextLineHeight.value = properties.lineHeight.toFixed(4);
|
elTextLineHeight.value = properties.lineHeight.toFixed(4);
|
||||||
|
elTextTextColor.style.backgroundColor = "rgb(" + properties.textColor.red + "," + properties.textColor.green + "," + properties.textColor.blue + ")";
|
||||||
elTextTextColorRed.value = properties.textColor.red;
|
elTextTextColorRed.value = properties.textColor.red;
|
||||||
elTextTextColorGreen.value = properties.textColor.green;
|
elTextTextColorGreen.value = properties.textColor.green;
|
||||||
elTextTextColorBlue.value = properties.textColor.blue;
|
elTextTextColorBlue.value = properties.textColor.blue;
|
||||||
|
@ -462,6 +489,7 @@
|
||||||
|
|
||||||
elLightSpotLight.checked = properties.isSpotlight;
|
elLightSpotLight.checked = properties.isSpotlight;
|
||||||
|
|
||||||
|
elLightColor.style.backgroundColor = "rgb(" + properties.color.red + "," + properties.color.green + "," + properties.color.blue + ")";
|
||||||
elLightColorRed.value = properties.color.red;
|
elLightColorRed.value = properties.color.red;
|
||||||
elLightColorGreen.value = properties.color.green;
|
elLightColorGreen.value = properties.color.green;
|
||||||
elLightColorBlue.value = properties.color.blue;
|
elLightColorBlue.value = properties.color.blue;
|
||||||
|
@ -475,6 +503,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled;
|
elZoneStageSunModelEnabled.checked = properties.stage.sunModelEnabled;
|
||||||
|
elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLightColor.red + "," + properties.keyLightColor.green + "," + properties.keyLightColor.blue + ")";
|
||||||
elZoneKeyLightColorRed.value = properties.keyLightColor.red;
|
elZoneKeyLightColorRed.value = properties.keyLightColor.red;
|
||||||
elZoneKeyLightColorGreen.value = properties.keyLightColor.green;
|
elZoneKeyLightColorGreen.value = properties.keyLightColor.green;
|
||||||
elZoneKeyLightColorBlue.value = properties.keyLightColor.blue;
|
elZoneKeyLightColorBlue.value = properties.keyLightColor.blue;
|
||||||
|
@ -495,6 +524,7 @@
|
||||||
|
|
||||||
elZoneBackgroundMode.value = properties.backgroundMode;
|
elZoneBackgroundMode.value = properties.backgroundMode;
|
||||||
|
|
||||||
|
elZoneSkyboxColor.style.backgroundColor = "rgb(" + properties.skybox.color.red + "," + properties.skybox.color.green + "," + properties.skybox.color.blue + ")";
|
||||||
elZoneSkyboxColorRed.value = properties.skybox.color.red;
|
elZoneSkyboxColorRed.value = properties.skybox.color.red;
|
||||||
elZoneSkyboxColorGreen.value = properties.skybox.color.green;
|
elZoneSkyboxColorGreen.value = properties.skybox.color.green;
|
||||||
elZoneSkyboxColorBlue.value = properties.skybox.color.blue;
|
elZoneSkyboxColorBlue.value = properties.skybox.color.blue;
|
||||||
|
@ -591,6 +621,16 @@
|
||||||
elColorRed.addEventListener('change', colorChangeFunction);
|
elColorRed.addEventListener('change', colorChangeFunction);
|
||||||
elColorGreen.addEventListener('change', colorChangeFunction);
|
elColorGreen.addEventListener('change', colorChangeFunction);
|
||||||
elColorBlue.addEventListener('change', colorChangeFunction);
|
elColorBlue.addEventListener('change', colorChangeFunction);
|
||||||
|
$('#property-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight'));
|
elLightSpotLight.addEventListener('change', createEmitCheckedPropertyUpdateFunction('isSpotlight'));
|
||||||
|
|
||||||
|
@ -599,6 +639,16 @@
|
||||||
elLightColorRed.addEventListener('change', lightColorChangeFunction);
|
elLightColorRed.addEventListener('change', lightColorChangeFunction);
|
||||||
elLightColorGreen.addEventListener('change', lightColorChangeFunction);
|
elLightColorGreen.addEventListener('change', lightColorChangeFunction);
|
||||||
elLightColorBlue.addEventListener('change', lightColorChangeFunction);
|
elLightColorBlue.addEventListener('change', lightColorChangeFunction);
|
||||||
|
$('#property-light-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity'));
|
elLightIntensity.addEventListener('change', createEmitNumberPropertyUpdateFunction('intensity'));
|
||||||
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent'));
|
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent'));
|
||||||
|
@ -622,14 +672,44 @@
|
||||||
elTextTextColorRed.addEventListener('change', textTextColorChangeFunction);
|
elTextTextColorRed.addEventListener('change', textTextColorChangeFunction);
|
||||||
elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction);
|
elTextTextColorGreen.addEventListener('change', textTextColorChangeFunction);
|
||||||
elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction);
|
elTextTextColorBlue.addEventListener('change', textTextColorChangeFunction);
|
||||||
|
$('#property-text-text-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
var textBackgroundColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||||
'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue);
|
'backgroundColor', elTextBackgroundColorRed, elTextBackgroundColorGreen, elTextBackgroundColorBlue);
|
||||||
elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction);
|
elTextBackgroundColorRed.addEventListener('change', textBackgroundColorChangeFunction);
|
||||||
elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction);
|
elTextBackgroundColorGreen.addEventListener('change', textBackgroundColorChangeFunction);
|
||||||
elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction);
|
elTextBackgroundColorBlue.addEventListener('change', textBackgroundColorChangeFunction);
|
||||||
|
$('#property-text-background-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled'));
|
elZoneStageSunModelEnabled.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('stage','sunModelEnabled'));
|
||||||
|
$('#property-zone-key-light-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('keyLightColor', rgb.r, rgb.g, rgb.b);
|
||||||
|
}
|
||||||
|
});
|
||||||
var zoneKeyLightColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
var zoneKeyLightColorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||||
'keyLightColor', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue);
|
'keyLightColor', elZoneKeyLightColorRed, elZoneKeyLightColorGreen, elZoneKeyLightColorBlue);
|
||||||
elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction);
|
elZoneKeyLightColorRed.addEventListener('change', zoneKeyLightColorChangeFunction);
|
||||||
|
@ -657,6 +737,16 @@
|
||||||
elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction);
|
elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction);
|
||||||
elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction);
|
elZoneSkyboxColorGreen.addEventListener('change', zoneSkyboxColorChangeFunction);
|
||||||
elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction);
|
elZoneSkyboxColorBlue.addEventListener('change', zoneSkyboxColorChangeFunction);
|
||||||
|
$('#property-zone-skybox-color').colpick({
|
||||||
|
colorScheme:'dark',
|
||||||
|
layout:'rgbhex',
|
||||||
|
color:'000000',
|
||||||
|
onSubmit: function(hsb, hex, rgb, el) {
|
||||||
|
$(el).css('background-color', '#'+hex);
|
||||||
|
$(el).colpickHide();
|
||||||
|
emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url'));
|
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url'));
|
||||||
|
|
||||||
|
@ -705,6 +795,12 @@
|
||||||
percentage: parseInt(elRescaleDimensionsPct.value),
|
percentage: parseInt(elRescaleDimensionsPct.value),
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
elCenterAtmosphereToZone.addEventListener("click", function() {
|
||||||
|
EventBridge.emitWebEvent(JSON.stringify({
|
||||||
|
type: "action",
|
||||||
|
action: "centerAtmosphereToZone",
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
window.onblur = function() {
|
window.onblur = function() {
|
||||||
// Fake a change event
|
// Fake a change event
|
||||||
|
@ -739,6 +835,7 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="properties" onload='loaded();'>
|
<body class="properties" onload='loaded();'>
|
||||||
|
@ -915,6 +1012,7 @@
|
||||||
<div id="color-section" class="property">
|
<div id="color-section" class="property">
|
||||||
<div class="label">Color</div>
|
<div class="label">Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div id="property-color" class='color-picker'></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-color-red"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-color-red"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-color-green"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-color-green"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-color-blue"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-color-blue"></input></div>
|
||||||
|
@ -1004,6 +1102,7 @@
|
||||||
<div class="text-section property">
|
<div class="text-section property">
|
||||||
<div class="label">Text Color</div>
|
<div class="label">Text Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div class='color-picker' id="property-text-text-color"></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-text-text-color-red"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-text-text-color-red"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-text-text-color-green"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-text-text-color-green"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-text-text-color-blue"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-text-text-color-blue"></input></div>
|
||||||
|
@ -1012,6 +1111,7 @@
|
||||||
<div class="text-section property">
|
<div class="text-section property">
|
||||||
<div class="label">Background Color</div>
|
<div class="label">Background Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div class='color-picker' id="property-text-background-color"></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-text-background-color-red"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-text-background-color-red"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-text-background-color-green"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-text-background-color-green"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-text-background-color-blue"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-text-background-color-blue"></input></div>
|
||||||
|
@ -1027,6 +1127,7 @@
|
||||||
<div class="light-section property">
|
<div class="light-section property">
|
||||||
<div class="label">Color</div>
|
<div class="label">Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div class='color-picker' id="property-light-color"></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-light-color-red"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-light-color-red"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-light-color-green"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-light-color-green"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-light-color-blue"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-light-color-blue"></input></div>
|
||||||
|
@ -1061,6 +1162,7 @@
|
||||||
<div class="zone-section property">
|
<div class="zone-section property">
|
||||||
<div class="label">Key Light Color</div>
|
<div class="label">Key Light Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div class='color-picker' id="property-zone-key-light-color"></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-zone-key-light-color-red" min="0" max="255" step="1"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-zone-key-light-color-red" min="0" max="255" step="1"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-zone-key-light-color-green" min="0" max="255" step="1"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-zone-key-light-color-green" min="0" max="255" step="1"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-zone-key-light-color-blue" min="0" max="255" step="1"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-zone-key-light-color-blue" min="0" max="255" step="1"></input></div>
|
||||||
|
@ -1139,6 +1241,7 @@
|
||||||
<div class="zone-section skybox-section property">
|
<div class="zone-section skybox-section property">
|
||||||
<div class="label">Skybox Color</div>
|
<div class="label">Skybox Color</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
|
<div class='color-picker' id="property-zone-skybox-color"></div>
|
||||||
<div class="input-area">R <input class="coord" type='number' id="property-zone-skybox-color-red"></input></div>
|
<div class="input-area">R <input class="coord" type='number' id="property-zone-skybox-color-red"></input></div>
|
||||||
<div class="input-area">G <input class="coord" type='number' id="property-zone-skybox-color-green"></input></div>
|
<div class="input-area">G <input class="coord" type='number' id="property-zone-skybox-color-green"></input></div>
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></input></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></input></div>
|
||||||
|
@ -1156,6 +1259,9 @@
|
||||||
<div class="input-area">X <br><input class="coord" type='number' id="property-zone-atmosphere-center-x"></input></div>
|
<div class="input-area">X <br><input class="coord" type='number' id="property-zone-atmosphere-center-x"></input></div>
|
||||||
<div class="input-area">Y <br><input class="coord" type='number' id="property-zone-atmosphere-center-y"></input></div>
|
<div class="input-area">Y <br><input class="coord" type='number' id="property-zone-atmosphere-center-y"></input></div>
|
||||||
<div class="input-area">Z <br><input class="coord" type='number' id="property-zone-atmosphere-center-z"></input></div>
|
<div class="input-area">Z <br><input class="coord" type='number' id="property-zone-atmosphere-center-z"></input></div>
|
||||||
|
<div>
|
||||||
|
<input type="button" id="center-atmosphere-in-zone" value="Center to Zone">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="zone-section atmosphere-section property">
|
<div class="zone-section atmosphere-section property">
|
||||||
|
|
4
examples/html/jquery-2.1.4.min.js
vendored
Normal file
4
examples/html/jquery-2.1.4.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -313,3 +313,10 @@ input[type="number"]::-webkit-inner-spin-button:active{
|
||||||
input#property-name {
|
input#property-name {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-picker {
|
||||||
|
width: 50px;
|
||||||
|
height: 10px;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
ZoneOverlayManager = function(isEntityFunc, entityAddedFunc, entityRemovedFunc, entityMovedFunc) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var visible = false;
|
|
||||||
|
|
||||||
// List of all created overlays
|
|
||||||
var allOverlays = [];
|
|
||||||
|
|
||||||
// List of overlays not currently being used
|
|
||||||
var unusedOverlays = [];
|
|
||||||
|
|
||||||
// Map from EntityItemID.id to overlay id
|
|
||||||
var entityOverlays = {};
|
|
||||||
|
|
||||||
// Map from EntityItemID.id to EntityItemID object
|
|
||||||
var entityIDs = {};
|
|
||||||
|
|
||||||
this.updatePositions = function(ids) {
|
|
||||||
for (var id in entityIDs) {
|
|
||||||
var entityID = entityIDs[id];
|
|
||||||
var properties = Entities.getEntityProperties(entityID);
|
|
||||||
Overlays.editOverlay(entityOverlays[entityID.id].solid, {
|
|
||||||
position: properties.position,
|
|
||||||
rotation: properties.rotation,
|
|
||||||
dimensions: properties.dimensions,
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(entityOverlays[entityID.id].outline, {
|
|
||||||
position: properties.position,
|
|
||||||
rotation: properties.rotation,
|
|
||||||
dimensions: properties.dimensions,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setVisible = function(isVisible) {
|
|
||||||
if (visible != isVisible) {
|
|
||||||
visible = isVisible;
|
|
||||||
Entities.setDrawZoneBoundaries(visible);
|
|
||||||
for (var id in entityOverlays) {
|
|
||||||
Overlays.editOverlay(entityOverlays[id].solid, { visible: visible });
|
|
||||||
Overlays.editOverlay(entityOverlays[id].outline, { visible: visible });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Allocate or get an unused overlay
|
|
||||||
function getOverlay() {
|
|
||||||
if (unusedOverlays.length == 0) {
|
|
||||||
var overlay = Overlays.addOverlay("cube", {
|
|
||||||
});
|
|
||||||
allOverlays.push(overlay);
|
|
||||||
} else {
|
|
||||||
var overlay = unusedOverlays.pop();
|
|
||||||
};
|
|
||||||
return overlay;
|
|
||||||
}
|
|
||||||
|
|
||||||
function releaseOverlay(overlay) {
|
|
||||||
unusedOverlays.push(overlay);
|
|
||||||
Overlays.editOverlay(overlay, { visible: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
function addEntity(entityID) {
|
|
||||||
var properties = Entities.getEntityProperties(entityID);
|
|
||||||
if (properties.type == "Zone" && !(entityID.id in entityOverlays)) {
|
|
||||||
var overlaySolid = getOverlay();
|
|
||||||
var overlayOutline = getOverlay();
|
|
||||||
|
|
||||||
entityOverlays[entityID.id] = {
|
|
||||||
solid: overlaySolid,
|
|
||||||
outline: overlayOutline,
|
|
||||||
}
|
|
||||||
entityIDs[entityID.id] = entityID;
|
|
||||||
|
|
||||||
var color = {
|
|
||||||
red: Math.round(Math.random() * 255),
|
|
||||||
green: Math.round(Math.random() * 255),
|
|
||||||
blue: Math.round(Math.random() * 255)
|
|
||||||
};
|
|
||||||
Overlays.editOverlay(overlaySolid, {
|
|
||||||
position: properties.position,
|
|
||||||
rotation: properties.rotation,
|
|
||||||
dimensions: properties.dimensions,
|
|
||||||
visible: visible,
|
|
||||||
solid: true,
|
|
||||||
alpha: 0.1,
|
|
||||||
color: color,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
});
|
|
||||||
Overlays.editOverlay(overlayOutline, {
|
|
||||||
position: properties.position,
|
|
||||||
rotation: properties.rotation,
|
|
||||||
dimensions: properties.dimensions,
|
|
||||||
visible: visible,
|
|
||||||
solid: false,
|
|
||||||
dashed: false,
|
|
||||||
lineWidth: 2.0,
|
|
||||||
alpha: 1.0,
|
|
||||||
color: color,
|
|
||||||
ignoreRayIntersection: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteEntity(entityID) {
|
|
||||||
if (entityID.id in entityOverlays) {
|
|
||||||
releaseOverlay(entityOverlays[entityID.id].outline);
|
|
||||||
releaseOverlay(entityOverlays[entityID.id].solid);
|
|
||||||
delete entityIDs[entityID.id];
|
|
||||||
delete entityOverlays[entityID.id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeEntityID(oldEntityID, newEntityID) {
|
|
||||||
entityOverlays[newEntityID.id] = entityOverlays[oldEntityID.id];
|
|
||||||
entityIDs[newEntityID.id] = newEntityID;
|
|
||||||
|
|
||||||
delete entityOverlays[oldEntityID.id];
|
|
||||||
delete entityIDs[oldEntityID.id];
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearEntities() {
|
|
||||||
for (var id in entityOverlays) {
|
|
||||||
releaseOverlay(entityOverlays[id].outline);
|
|
||||||
releaseOverlay(entityOverlays[id].solid);
|
|
||||||
}
|
|
||||||
entityOverlays = {};
|
|
||||||
entityIDs = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Entities.addingEntity.connect(addEntity);
|
|
||||||
Entities.changingEntityID.connect(changeEntityID);
|
|
||||||
Entities.deletingEntity.connect(deleteEntity);
|
|
||||||
Entities.clearingEntities.connect(clearEntities);
|
|
||||||
|
|
||||||
// Add existing entities
|
|
||||||
var ids = Entities.findEntities(MyAvatar.position, 64000);
|
|
||||||
for (var i = 0; i < ids.length; i++) {
|
|
||||||
addEntity(ids[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Script.scriptEnding.connect(function() {
|
|
||||||
for (var i = 0; i < allOverlays.length; i++) {
|
|
||||||
Overlays.deleteOverlay(allOverlays[i]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -3223,18 +3223,40 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
|
||||||
// compute starfield alpha based on distance from atmosphere
|
// compute starfield alpha based on distance from atmosphere
|
||||||
float alpha = 1.0f;
|
float alpha = 1.0f;
|
||||||
bool hasStars = true;
|
bool hasStars = true;
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
||||||
// TODO: handle this correctly for zones
|
// TODO: handle this correctly for zones
|
||||||
const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition());
|
const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition());
|
||||||
|
|
||||||
if (closestData.getHasStars()) {
|
if (closestData.getHasStars()) {
|
||||||
|
const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f;
|
||||||
|
const float DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON = 0.2f;
|
||||||
|
|
||||||
|
glm::vec3 sunDirection = (getAvatarPosition() - closestData.getSunLocation())
|
||||||
|
/ closestData.getAtmosphereOuterRadius();
|
||||||
float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter());
|
float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter());
|
||||||
if (height < closestData.getAtmosphereInnerRadius()) {
|
if (height < closestData.getAtmosphereInnerRadius()) {
|
||||||
|
// If we're inside the atmosphere, then determine if our keyLight is below the horizon
|
||||||
alpha = 0.0f;
|
alpha = 0.0f;
|
||||||
|
|
||||||
|
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
||||||
|
float directionY = glm::clamp(sunDirection.y,
|
||||||
|
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
||||||
|
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
||||||
|
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else if (height < closestData.getAtmosphereOuterRadius()) {
|
} else if (height < closestData.getAtmosphereOuterRadius()) {
|
||||||
alpha = (height - closestData.getAtmosphereInnerRadius()) /
|
alpha = (height - closestData.getAtmosphereInnerRadius()) /
|
||||||
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
|
(closestData.getAtmosphereOuterRadius() - closestData.getAtmosphereInnerRadius());
|
||||||
|
|
||||||
|
if (sunDirection.y > -APPROXIMATE_DISTANCE_FROM_HORIZON) {
|
||||||
|
float directionY = glm::clamp(sunDirection.y,
|
||||||
|
-APPROXIMATE_DISTANCE_FROM_HORIZON, APPROXIMATE_DISTANCE_FROM_HORIZON)
|
||||||
|
+ APPROXIMATE_DISTANCE_FROM_HORIZON;
|
||||||
|
alpha = (directionY / DOUBLE_APPROXIMATE_DISTANCE_FROM_HORIZON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hasStars = false;
|
hasStars = false;
|
||||||
|
|
|
@ -183,8 +183,8 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
|
||||||
_filteredEyeBlinks(),
|
_filteredEyeBlinks(),
|
||||||
_lastEyeCoefficients(),
|
_lastEyeCoefficients(),
|
||||||
_isCalibrating(false),
|
_isCalibrating(false),
|
||||||
_calibrationValues(),
|
|
||||||
_calibrationCount(0),
|
_calibrationCount(0),
|
||||||
|
_calibrationValues(),
|
||||||
_calibrationBillboard(NULL),
|
_calibrationBillboard(NULL),
|
||||||
_calibrationBillboardID(0),
|
_calibrationBillboardID(0),
|
||||||
_calibrationMessage(QString())
|
_calibrationMessage(QString())
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
ClipboardScriptingInterface::ClipboardScriptingInterface() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ClipboardScriptingInterface::getClipboardContentsLargestDimension() {
|
||||||
|
return Application::getInstance()->getEntityClipboard()->getContentsLargestDimension();
|
||||||
|
}
|
||||||
|
|
||||||
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
bool ClipboardScriptingInterface::exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs) {
|
||||||
return Application::getInstance()->exportEntities(filename, entityIDs);
|
return Application::getInstance()->exportEntities(filename, entityIDs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ signals:
|
||||||
void readyToImport();
|
void readyToImport();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
float getClipboardContentsLargestDimension(); /// returns the largest dimension of everything on the clipboard
|
||||||
bool importEntities(const QString& filename);
|
bool importEntities(const QString& filename);
|
||||||
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs);
|
bool exportEntities(const QString& filename, const QVector<EntityItemID>& entityIDs);
|
||||||
bool exportEntities(const QString& filename, float x, float y, float z, float s);
|
bool exportEntities(const QString& filename, float x, float y, float z, float s);
|
||||||
|
|
|
@ -1226,19 +1226,17 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(const glm::vec2& sphericalPos)
|
||||||
result /= _textureFov;
|
result /= _textureFov;
|
||||||
result.x /= _textureAspectRatio;
|
result.x /= _textureAspectRatio;
|
||||||
result += 0.5f;
|
result += 0.5f;
|
||||||
result.x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f);
|
|
||||||
result.y = (sphericalPos.y / _textureFov + 0.5f);
|
|
||||||
result *= qApp->getCanvasSize();
|
result *= qApp->getCanvasSize();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec2 ApplicationOverlay::overlayToSpherical(const glm::vec2& overlayPos) const {
|
glm::vec2 ApplicationOverlay::overlayToSpherical(const glm::vec2& overlayPos) const {
|
||||||
glm::vec2 result = overlayPos;
|
glm::vec2 result = overlayPos;
|
||||||
result.x *= -1.0;
|
|
||||||
result /= qApp->getCanvasSize();
|
result /= qApp->getCanvasSize();
|
||||||
result -= 0.5f;
|
result -= 0.5f;
|
||||||
result *= _textureFov;
|
result *= _textureFov;
|
||||||
result.x *= _textureAspectRatio;
|
result.x *= _textureAspectRatio;
|
||||||
|
result.x *= -1.0f;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <DeferredLightingEffect.h>
|
#include <DeferredLightingEffect.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
|
#include "EntitiesRendererLogging.h"
|
||||||
|
|
||||||
#include "RenderableParticleEffectEntityItem.h"
|
#include "RenderableParticleEffectEntityItem.h"
|
||||||
|
|
||||||
|
@ -29,62 +30,158 @@ RenderableParticleEffectEntityItem::RenderableParticleEffectEntityItem(const Ent
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderableParticleEffectEntityItem::render(RenderArgs* args) {
|
void RenderableParticleEffectEntityItem::render(RenderArgs* args) {
|
||||||
PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render");
|
|
||||||
assert(getType() == EntityTypes::ParticleEffect);
|
assert(getType() == EntityTypes::ParticleEffect);
|
||||||
float pa_rad = getParticleRadius();
|
PerformanceTimer perfTimer("RenderableParticleEffectEntityItem::render");
|
||||||
|
|
||||||
const float MAX_COLOR = 255.0f;
|
if (_texturesChangedFlag) {
|
||||||
glm::vec4 paColor(getColor()[RED_INDEX] / MAX_COLOR, getColor()[GREEN_INDEX] / MAX_COLOR,
|
if (_textures.isEmpty()) {
|
||||||
getColor()[BLUE_INDEX] / MAX_COLOR, getLocalRenderAlpha());
|
_texture.clear();
|
||||||
|
} else {
|
||||||
// Right now we're just iterating over particles and rendering as a cross of four quads.
|
// for now use the textures string directly.
|
||||||
// This is pretty dumb, it was quick enough to code up. Really, there should be many
|
// Eventually we'll want multiple textures in a map or array.
|
||||||
// rendering modes, including the all-important textured billboards.
|
_texture = DependencyManager::get<TextureCache>()->getTexture(_textures);
|
||||||
|
}
|
||||||
QVector<glm::vec3>* pointVec = new QVector<glm::vec3>(_paCount * VERTS_PER_PARTICLE);
|
_texturesChangedFlag = false;
|
||||||
quint32 paIter = _paHead;
|
|
||||||
while (_paLife[paIter] > 0.0f) {
|
|
||||||
int j = paIter * XYZ_STRIDE;
|
|
||||||
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2]));
|
|
||||||
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] + pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] - pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2]));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j] + pa_rad, _paPosition[j + 1] - pa_rad, _paPosition[j + 2]));
|
|
||||||
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] - pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] + pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] + pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] - pa_rad));
|
|
||||||
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] + pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] + pa_rad, _paPosition[j + 2] - pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] - pa_rad));
|
|
||||||
pointVec->append(glm::vec3(_paPosition[j], _paPosition[j + 1] - pa_rad, _paPosition[j + 2] + pa_rad));
|
|
||||||
|
|
||||||
paIter = (paIter + 1) % _maxParticles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->updateVertices(_cacheID, *pointVec, paColor);
|
if (!_texture) {
|
||||||
|
renderUntexturedQuads(args);
|
||||||
|
} else if (_texture && !_texture->isLoaded()) {
|
||||||
|
renderUntexturedQuads(args);
|
||||||
|
} else {
|
||||||
|
renderTexturedQuads(args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void RenderableParticleEffectEntityItem::renderUntexturedQuads(RenderArgs* args) {
|
||||||
|
|
||||||
|
float particleRadius = getParticleRadius();
|
||||||
|
|
||||||
|
const float MAX_COLOR = 255.0f;
|
||||||
|
glm::vec4 particleColor(getColor()[RED_INDEX] / MAX_COLOR,
|
||||||
|
getColor()[GREEN_INDEX] / MAX_COLOR,
|
||||||
|
getColor()[BLUE_INDEX] / MAX_COLOR,
|
||||||
|
getLocalRenderAlpha());
|
||||||
|
|
||||||
|
glm::vec3 upOffset = args->_viewFrustum->getUp() * particleRadius;
|
||||||
|
glm::vec3 rightOffset = args->_viewFrustum->getRight() * particleRadius;
|
||||||
|
|
||||||
|
QVector<glm::vec3> vertices(getLivingParticleCount() * VERTS_PER_PARTICLE);
|
||||||
|
quint32 count = 0;
|
||||||
|
for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) {
|
||||||
|
glm::vec3 pos = _particlePositions[i];
|
||||||
|
|
||||||
|
// generate corners of quad, aligned to face the camera
|
||||||
|
vertices.append(pos - rightOffset + upOffset);
|
||||||
|
vertices.append(pos + rightOffset + upOffset);
|
||||||
|
vertices.append(pos + rightOffset - upOffset);
|
||||||
|
vertices.append(pos - rightOffset - upOffset);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just double checking, cause if this invarient is false, we might have memory corruption bugs.
|
||||||
|
assert(count == getLivingParticleCount());
|
||||||
|
|
||||||
|
// update geometry cache with all the verts in model coordinates.
|
||||||
|
DependencyManager::get<GeometryCache>()->updateVertices(_cacheID, vertices, particleColor);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
glm::vec3 position = getPosition();
|
glm::vec3 position = getPosition();
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
glm::quat rotation = getRotation();
|
glm::quat rotation = getRotation();
|
||||||
glm::vec3 axis = glm::axis(rotation);
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
|
||||||
glm::vec3 positionToCenter = getCenter() - position;
|
glm::vec3 positionToCenter = getCenter() - position;
|
||||||
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderVertices(gpu::QUADS, _cacheID);
|
DependencyManager::get<GeometryCache>()->renderVertices(gpu::QUADS, _cacheID);
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
static glm::vec3 zSortAxis;
|
||||||
|
static bool zSort(const glm::vec3& rhs, const glm::vec3& lhs) {
|
||||||
|
return glm::dot(rhs, ::zSortAxis) > glm::dot(lhs, ::zSortAxis);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableParticleEffectEntityItem::renderTexturedQuads(RenderArgs* args) {
|
||||||
|
|
||||||
|
float particleRadius = getParticleRadius();
|
||||||
|
|
||||||
|
const float MAX_COLOR = 255.0f;
|
||||||
|
glm::vec4 particleColor(getColor()[RED_INDEX] / MAX_COLOR,
|
||||||
|
getColor()[GREEN_INDEX] / MAX_COLOR,
|
||||||
|
getColor()[BLUE_INDEX] / MAX_COLOR,
|
||||||
|
getLocalRenderAlpha());
|
||||||
|
|
||||||
|
QVector<glm::vec3> positions(getLivingParticleCount());
|
||||||
|
quint32 count = 0;
|
||||||
|
for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) {
|
||||||
|
positions.append(_particlePositions[i]);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// just double checking, cause if this invarient is false, we might have memory corruption bugs.
|
||||||
|
assert(count == getLivingParticleCount());
|
||||||
|
|
||||||
|
// sort particles back to front
|
||||||
|
::zSortAxis = args->_viewFrustum->getDirection();
|
||||||
|
qSort(positions.begin(), positions.end(), zSort);
|
||||||
|
|
||||||
|
QVector<glm::vec3> vertices(getLivingParticleCount() * VERTS_PER_PARTICLE);
|
||||||
|
QVector<glm::vec2> textureCoords(getLivingParticleCount() * VERTS_PER_PARTICLE);
|
||||||
|
|
||||||
|
glm::vec3 upOffset = args->_viewFrustum->getUp() * particleRadius;
|
||||||
|
glm::vec3 rightOffset = args->_viewFrustum->getRight() * particleRadius;
|
||||||
|
|
||||||
|
for (int i = 0; i < positions.size(); i++) {
|
||||||
|
glm::vec3 pos = positions[i];
|
||||||
|
|
||||||
|
// generate corners of quad aligned to face the camera.
|
||||||
|
vertices.append(pos - rightOffset + upOffset);
|
||||||
|
vertices.append(pos + rightOffset + upOffset);
|
||||||
|
vertices.append(pos + rightOffset - upOffset);
|
||||||
|
vertices.append(pos - rightOffset - upOffset);
|
||||||
|
|
||||||
|
textureCoords.append(glm::vec2(0, 1));
|
||||||
|
textureCoords.append(glm::vec2(1, 1));
|
||||||
|
textureCoords.append(glm::vec2(1, 0));
|
||||||
|
textureCoords.append(glm::vec2(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// update geometry cache with all the verts in model coordinates.
|
||||||
|
DependencyManager::get<GeometryCache>()->updateVertices(_cacheID, vertices, textureCoords, particleColor);
|
||||||
|
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, _texture->getID());
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glm::vec3 position = getPosition();
|
||||||
|
glTranslatef(position.x, position.y, position.z);
|
||||||
|
glm::quat rotation = getRotation();
|
||||||
|
glm::vec3 axis = glm::axis(rotation);
|
||||||
|
glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glm::vec3 positionToCenter = getCenter() - position;
|
||||||
|
glTranslatef(positionToCenter.x, positionToCenter.y, positionToCenter.z);
|
||||||
|
|
||||||
|
DependencyManager::get<GeometryCache>()->renderVertices(gpu::QUADS, _cacheID);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
delete pointVec;
|
glDisable(GL_TEXTURE_2D);
|
||||||
};
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define hifi_RenderableParticleEffectEntityItem_h
|
#define hifi_RenderableParticleEffectEntityItem_h
|
||||||
|
|
||||||
#include <ParticleEffectEntityItem.h>
|
#include <ParticleEffectEntityItem.h>
|
||||||
|
#include <TextureCache.h>
|
||||||
|
|
||||||
class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem {
|
class RenderableParticleEffectEntityItem : public ParticleEffectEntityItem {
|
||||||
public:
|
public:
|
||||||
|
@ -19,9 +20,15 @@ public:
|
||||||
RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
RenderableParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||||
virtual void render(RenderArgs* args);
|
virtual void render(RenderArgs* args);
|
||||||
|
|
||||||
|
void renderUntexturedQuads(RenderArgs* args);
|
||||||
|
void renderTexturedQuads(RenderArgs* args);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
int _cacheID;
|
int _cacheID;
|
||||||
const int VERTS_PER_PARTICLE = 16;
|
const int VERTS_PER_PARTICLE = 4;
|
||||||
|
|
||||||
|
NetworkTexturePointer _texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1068,6 +1068,27 @@ void EntityTree::debugDumpMap() {
|
||||||
qCDebug(entities) << "-----------------------------------------------------";
|
qCDebug(entities) << "-----------------------------------------------------";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContentsDimensionOperator : public RecurseOctreeOperator {
|
||||||
|
public:
|
||||||
|
virtual bool preRecursion(OctreeElement* element);
|
||||||
|
virtual bool postRecursion(OctreeElement* element) { return true; }
|
||||||
|
float getLargestDimension() const { return _contentExtents.largestDimension(); }
|
||||||
|
private:
|
||||||
|
Extents _contentExtents;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ContentsDimensionOperator::preRecursion(OctreeElement* element) {
|
||||||
|
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||||
|
entityTreeElement->expandExtentsToContents(_contentExtents);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float EntityTree::getContentsLargestDimension() {
|
||||||
|
ContentsDimensionOperator theOperator;
|
||||||
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
return theOperator.getLargestDimension();
|
||||||
|
}
|
||||||
|
|
||||||
class DebugOperator : public RecurseOctreeOperator {
|
class DebugOperator : public RecurseOctreeOperator {
|
||||||
public:
|
public:
|
||||||
virtual bool preRecursion(OctreeElement* element);
|
virtual bool preRecursion(OctreeElement* element);
|
||||||
|
|
|
@ -166,6 +166,8 @@ public:
|
||||||
|
|
||||||
bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues);
|
bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues);
|
||||||
bool readFromMap(QVariantMap& entityDescription);
|
bool readFromMap(QVariantMap& entityDescription);
|
||||||
|
|
||||||
|
float getContentsLargestDimension();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deletingEntity(const EntityItemID& entityID);
|
void deletingEntity(const EntityItemID& entityID);
|
||||||
|
|
|
@ -819,6 +819,16 @@ bool EntityTreeElement::pruneChildren() {
|
||||||
return somethingPruned;
|
return somethingPruned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTreeElement::expandExtentsToContents(Extents& extents) {
|
||||||
|
if (_entityItems->size()) {
|
||||||
|
for (uint16_t i = 0; i < _entityItems->size(); i++) {
|
||||||
|
EntityItem* entity = (*_entityItems)[i];
|
||||||
|
extents.add(entity->getAABox());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void EntityTreeElement::debugDump() {
|
void EntityTreeElement::debugDump() {
|
||||||
qCDebug(entities) << "EntityTreeElement...";
|
qCDebug(entities) << "EntityTreeElement...";
|
||||||
|
|
|
@ -196,6 +196,8 @@ public:
|
||||||
|
|
||||||
bool pruneChildren();
|
bool pruneChildren();
|
||||||
|
|
||||||
|
void expandExtentsToContents(Extents& extents);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void init(unsigned char * octalCode);
|
virtual void init(unsigned char * octalCode);
|
||||||
EntityTree* _myTree;
|
EntityTree* _myTree;
|
||||||
|
|
|
@ -18,12 +18,8 @@
|
||||||
// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented).
|
// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented).
|
||||||
// - Add drag.
|
// - Add drag.
|
||||||
// - Add some kind of support for collisions.
|
// - Add some kind of support for collisions.
|
||||||
// - For simplicity, I'm currently just rendering each particle as a cross of four axis-aligned quads. Really, we'd
|
|
||||||
// want multiple render modes, including (the most important) textured billboards (always facing camera). Also, these
|
|
||||||
// should support animated textures.
|
|
||||||
// - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so
|
// - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so
|
||||||
// there's no gaurantee that different clients will see simulations that look anything like the other.
|
// there's no gaurantee that different clients will see simulations that look anything like the other.
|
||||||
// - MORE?
|
|
||||||
//
|
//
|
||||||
// Created by Jason Rickwald on 3/2/15.
|
// Created by Jason Rickwald on 3/2/15.
|
||||||
//
|
//
|
||||||
|
@ -45,6 +41,7 @@
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "ParticleEffectEntityItem.h"
|
#include "ParticleEffectEntityItem.h"
|
||||||
|
|
||||||
|
const xColor ParticleEffectEntityItem::DEFAULT_COLOR = { 255, 255, 255 };
|
||||||
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
|
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
|
||||||
const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
|
const bool ParticleEffectEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
|
||||||
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f;
|
const float ParticleEffectEntityItem::DEFAULT_ANIMATION_FPS = 30.0f;
|
||||||
|
@ -55,6 +52,7 @@ const glm::vec3 ParticleEffectEntityItem::DEFAULT_EMIT_DIRECTION(0.0f, 1.0f, 0.0
|
||||||
const float ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH = 25.0f;
|
const float ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH = 25.0f;
|
||||||
const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f;
|
const float ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY = -9.8f;
|
||||||
const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f;
|
const float ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS = 0.025f;
|
||||||
|
const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = "";
|
||||||
|
|
||||||
|
|
||||||
EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
|
@ -63,40 +61,40 @@ EntityItem* ParticleEffectEntityItem::factory(const EntityItemID& entityID, cons
|
||||||
|
|
||||||
// our non-pure virtual subclass for now...
|
// our non-pure virtual subclass for now...
|
||||||
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||||
EntityItem(entityItemID, properties) {
|
EntityItem(entityItemID, properties),
|
||||||
|
_maxParticles(DEFAULT_MAX_PARTICLES),
|
||||||
|
_lifespan(DEFAULT_LIFESPAN),
|
||||||
|
_emitRate(DEFAULT_EMIT_RATE),
|
||||||
|
_emitDirection(DEFAULT_EMIT_DIRECTION),
|
||||||
|
_emitStrength(DEFAULT_EMIT_STRENGTH),
|
||||||
|
_localGravity(DEFAULT_LOCAL_GRAVITY),
|
||||||
|
_particleRadius(DEFAULT_PARTICLE_RADIUS),
|
||||||
|
_lastAnimated(usecTimestampNow()),
|
||||||
|
_animationLoop(),
|
||||||
|
_animationSettings(),
|
||||||
|
_textures(DEFAULT_TEXTURES),
|
||||||
|
_texturesChangedFlag(false),
|
||||||
|
_shapeType(SHAPE_TYPE_NONE),
|
||||||
|
_particleLifetimes(DEFAULT_MAX_PARTICLES, 0.0f),
|
||||||
|
_particlePositions(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||||
|
_particleVelocities(DEFAULT_MAX_PARTICLES, glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||||
|
_timeUntilNextEmit(0.0f),
|
||||||
|
_particleHeadIndex(0),
|
||||||
|
_particleTailIndex(0),
|
||||||
|
_particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)),
|
||||||
|
_particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) {
|
||||||
|
|
||||||
_type = EntityTypes::ParticleEffect;
|
_type = EntityTypes::ParticleEffect;
|
||||||
_maxParticles = DEFAULT_MAX_PARTICLES;
|
setColor(DEFAULT_COLOR);
|
||||||
_lifespan = DEFAULT_LIFESPAN;
|
|
||||||
_emitRate = DEFAULT_EMIT_RATE;
|
|
||||||
_emitDirection = DEFAULT_EMIT_DIRECTION;
|
|
||||||
_emitStrength = DEFAULT_EMIT_STRENGTH;
|
|
||||||
_localGravity = DEFAULT_LOCAL_GRAVITY;
|
|
||||||
_particleRadius = DEFAULT_PARTICLE_RADIUS;
|
|
||||||
setProperties(properties);
|
setProperties(properties);
|
||||||
// this is a pretty dumb thing to do, and it should probably be changed to use a more dynamic
|
|
||||||
// data structure in the future. I'm just trying to get some code out the door for now (and it's
|
|
||||||
// at least time efficient (though not space efficient).
|
|
||||||
// Also, this being a real-time application, it's doubtful we'll ever have millions of particles
|
|
||||||
// to keep track of, so this really isn't all that bad.
|
|
||||||
_paLife = new float[_maxParticles];
|
|
||||||
_paPosition = new float[_maxParticles * XYZ_STRIDE]; // x,y,z
|
|
||||||
_paVelocity = new float[_maxParticles * XYZ_STRIDE]; // x,y,z
|
|
||||||
_paXmax = _paYmax = _paZmax = 1.0f;
|
|
||||||
_paXmin = _paYmin = _paZmin = -1.0f;
|
|
||||||
_randSeed = (unsigned int) glm::abs(_lifespan + _emitRate + _localGravity + getPosition().x + getPosition().y + getPosition().z);
|
|
||||||
resetSimulation();
|
|
||||||
_lastAnimated = usecTimestampNow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleEffectEntityItem::~ParticleEffectEntityItem() {
|
ParticleEffectEntityItem::~ParticleEffectEntityItem() {
|
||||||
delete [] _paLife;
|
|
||||||
delete [] _paPosition;
|
|
||||||
delete [] _paVelocity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemProperties ParticleEffectEntityItem::getProperties() const {
|
EntityItemProperties ParticleEffectEntityItem::getProperties() const {
|
||||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||||
|
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex);
|
||||||
|
@ -111,6 +109,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties() const {
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitStrength, getEmitStrength);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localGravity, getLocalGravity);
|
||||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius);
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleRadius, getParticleRadius);
|
||||||
|
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +131,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitStrength, setEmitStrength);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localGravity, setLocalGravity);
|
||||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius);
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleRadius, setParticleRadius);
|
||||||
|
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||||
|
|
||||||
if (somethingChanged) {
|
if (somethingChanged) {
|
||||||
bool wantDebug = false;
|
bool wantDebug = false;
|
||||||
|
@ -147,8 +147,8 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
ReadBitstreamToTreeParams& args,
|
ReadBitstreamToTreeParams& args,
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
|
||||||
|
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
const unsigned char* dataAt = data;
|
const unsigned char* dataAt = data;
|
||||||
|
@ -186,6 +186,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
||||||
READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength);
|
READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, _emitStrength);
|
||||||
READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity);
|
READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, _localGravity);
|
||||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius);
|
READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, _particleRadius);
|
||||||
|
READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures);
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +195,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
||||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||||
EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||||
|
|
||||||
requestedProperties += PROP_COLOR;
|
requestedProperties += PROP_COLOR;
|
||||||
requestedProperties += PROP_ANIMATION_FPS;
|
requestedProperties += PROP_ANIMATION_FPS;
|
||||||
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
|
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
|
||||||
|
@ -208,17 +209,18 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
|
||||||
requestedProperties += PROP_EMIT_STRENGTH;
|
requestedProperties += PROP_EMIT_STRENGTH;
|
||||||
requestedProperties += PROP_LOCAL_GRAVITY;
|
requestedProperties += PROP_LOCAL_GRAVITY;
|
||||||
requestedProperties += PROP_PARTICLE_RADIUS;
|
requestedProperties += PROP_PARTICLE_RADIUS;
|
||||||
|
requestedProperties += PROP_TEXTURES;
|
||||||
|
|
||||||
return requestedProperties;
|
return requestedProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||||
EntityPropertyFlags& requestedProperties,
|
EntityPropertyFlags& requestedProperties,
|
||||||
EntityPropertyFlags& propertyFlags,
|
EntityPropertyFlags& propertyFlags,
|
||||||
EntityPropertyFlags& propertiesDidntFit,
|
EntityPropertyFlags& propertiesDidntFit,
|
||||||
int& propertyCount,
|
int& propertyCount,
|
||||||
OctreeElement::AppendState& appendState) const {
|
OctreeElement::AppendState& appendState) const {
|
||||||
|
|
||||||
bool successPropertyFits = true;
|
bool successPropertyFits = true;
|
||||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||||
|
@ -234,11 +236,12 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
||||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength());
|
APPEND_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, appendValue, getEmitStrength());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity());
|
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, appendValue, getLocalGravity());
|
||||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius());
|
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, getParticleRadius());
|
||||||
|
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParticleEffectEntityItem::isAnimatingSomething() const {
|
bool ParticleEffectEntityItem::isAnimatingSomething() const {
|
||||||
return getAnimationIsPlaying() &&
|
// keep animating if there are particles still alive.
|
||||||
getAnimationFPS() != 0.0f;
|
return (getAnimationIsPlaying() || getLivingParticleCount() > 0) && getAnimationFPS() != 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParticleEffectEntityItem::needsToCallUpdate() const {
|
bool ParticleEffectEntityItem::needsToCallUpdate() const {
|
||||||
|
@ -246,33 +249,25 @@ bool ParticleEffectEntityItem::needsToCallUpdate() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityItem::update(const quint64& now) {
|
void ParticleEffectEntityItem::update(const quint64& now) {
|
||||||
|
|
||||||
|
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
|
||||||
|
_lastAnimated = now;
|
||||||
|
|
||||||
// only advance the frame index if we're playing
|
// only advance the frame index if we're playing
|
||||||
if (getAnimationIsPlaying()) {
|
if (getAnimationIsPlaying()) {
|
||||||
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
|
|
||||||
_lastAnimated = now;
|
|
||||||
float lastFrame = _animationLoop.getFrameIndex();
|
|
||||||
_animationLoop.simulate(deltaTime);
|
_animationLoop.simulate(deltaTime);
|
||||||
float curFrame = _animationLoop.getFrameIndex();
|
|
||||||
if (curFrame > lastFrame) {
|
|
||||||
stepSimulation(deltaTime);
|
|
||||||
}
|
|
||||||
else if (curFrame < lastFrame) {
|
|
||||||
// we looped around, so restart the sim and only sim up to the point
|
|
||||||
// since the beginning of the frame range.
|
|
||||||
resetSimulation();
|
|
||||||
stepSimulation((curFrame - _animationLoop.getFirstFrame()) / _animationLoop.getFPS());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_lastAnimated = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the dimensions
|
if (isAnimatingSomething()) {
|
||||||
glm::vec3 dims;
|
stepSimulation(deltaTime);
|
||||||
dims.x = glm::max(glm::abs(_paXmin), glm::abs(_paXmax)) * 2.0f;
|
|
||||||
dims.y = glm::max(glm::abs(_paYmin), glm::abs(_paYmax)) * 2.0f;
|
// update the dimensions
|
||||||
dims.z = glm::max(glm::abs(_paZmin), glm::abs(_paZmax)) * 2.0f;
|
glm::vec3 dims;
|
||||||
setDimensions(dims);
|
dims.x = glm::max(glm::abs(_particleMinBound.x), glm::abs(_particleMaxBound.x)) * 2.0f;
|
||||||
|
dims.y = glm::max(glm::abs(_particleMinBound.y), glm::abs(_particleMaxBound.y)) * 2.0f;
|
||||||
|
dims.z = glm::max(glm::abs(_particleMinBound.z), glm::abs(_particleMaxBound.z)) * 2.0f;
|
||||||
|
setDimensions(dims);
|
||||||
|
}
|
||||||
|
|
||||||
EntityItem::update(now); // let our base class handle it's updates...
|
EntityItem::update(now); // let our base class handle it's updates...
|
||||||
}
|
}
|
||||||
|
@ -418,96 +413,103 @@ QString ParticleEffectEntityItem::getAnimationSettings() const {
|
||||||
return jsonByteString;
|
return jsonByteString;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) {
|
||||||
_paXmin = _paYmin = _paZmin = -1.0f;
|
_particleMinBound.x = glm::min(_particleMinBound.x, point.x);
|
||||||
_paXmax = _paYmax = _paZmax = 1.0f;
|
_particleMinBound.y = glm::min(_particleMinBound.y, point.y);
|
||||||
|
_particleMinBound.z = glm::min(_particleMinBound.z, point.z);
|
||||||
|
_particleMaxBound.x = glm::max(_particleMaxBound.x, point.x);
|
||||||
|
_particleMaxBound.y = glm::max(_particleMaxBound.y, point.y);
|
||||||
|
_particleMaxBound.z = glm::max(_particleMaxBound.z, point.z);
|
||||||
|
}
|
||||||
|
|
||||||
// update particles
|
void ParticleEffectEntityItem::integrateParticle(quint32 index, float deltaTime) {
|
||||||
quint32 updateIter = _paHead;
|
glm::vec3 atSquared(0.0f, 0.5f * _localGravity * deltaTime * deltaTime, 0.0f);
|
||||||
while (_paLife[updateIter] > 0.0f) {
|
glm::vec3 at(0.0f, _localGravity * deltaTime, 0.0f);
|
||||||
_paLife[updateIter] -= deltaTime;
|
_particlePositions[index] += _particleVelocities[index] * deltaTime + atSquared;
|
||||||
if (_paLife[updateIter] <= 0.0f) {
|
_particleVelocities[index] += at;
|
||||||
_paLife[updateIter] = -1.0f;
|
}
|
||||||
_paHead = (_paHead + 1) % _maxParticles;
|
|
||||||
_paCount--;
|
void ParticleEffectEntityItem::stepSimulation(float deltaTime) {
|
||||||
|
|
||||||
|
_particleMinBound = glm::vec3(-1.0f, -1.0f, -1.0f);
|
||||||
|
_particleMaxBound = glm::vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
// update particles between head and tail
|
||||||
|
for (quint32 i = _particleHeadIndex; i != _particleTailIndex; i = (i + 1) % _maxParticles) {
|
||||||
|
_particleLifetimes[i] -= deltaTime;
|
||||||
|
|
||||||
|
// if particle has died.
|
||||||
|
if (_particleLifetimes[i] <= 0.0f) {
|
||||||
|
// move head forward
|
||||||
|
_particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// DUMB FORWARD EULER just to get it done
|
integrateParticle(i, deltaTime);
|
||||||
int j = updateIter * XYZ_STRIDE;
|
extendBounds(_particlePositions[i]);
|
||||||
_paPosition[j] += _paVelocity[j] * deltaTime;
|
|
||||||
_paPosition[j+1] += _paVelocity[j+1] * deltaTime;
|
|
||||||
_paPosition[j+2] += _paVelocity[j+2] * deltaTime;
|
|
||||||
|
|
||||||
_paXmin = glm::min(_paXmin, _paPosition[j]);
|
|
||||||
_paYmin = glm::min(_paYmin, _paPosition[j+1]);
|
|
||||||
_paZmin = glm::min(_paZmin, _paPosition[j+2]);
|
|
||||||
_paXmax = glm::max(_paXmax, _paPosition[j]);
|
|
||||||
_paYmax = glm::max(_paYmax, _paPosition[j + 1]);
|
|
||||||
_paZmax = glm::max(_paZmax, _paPosition[j + 2]);
|
|
||||||
|
|
||||||
// massless particles
|
|
||||||
_paVelocity[j + 1] += deltaTime * _localGravity;
|
|
||||||
}
|
}
|
||||||
updateIter = (updateIter + 1) % _maxParticles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit new particles
|
// emit new particles, but only if animaiton is playing
|
||||||
quint32 emitIdx = updateIter;
|
if (getAnimationIsPlaying()) {
|
||||||
_partialEmit += ((float)_emitRate) * deltaTime;
|
|
||||||
quint32 birthed = (quint32)_partialEmit;
|
|
||||||
_partialEmit -= (float)birthed;
|
|
||||||
glm::vec3 randOffset;
|
|
||||||
|
|
||||||
for (quint32 i = 0; i < birthed; i++) {
|
float timeLeftInFrame = deltaTime;
|
||||||
if (_paLife[emitIdx] < 0.0f) {
|
while (_timeUntilNextEmit < timeLeftInFrame) {
|
||||||
int j = emitIdx * XYZ_STRIDE;
|
|
||||||
_paLife[emitIdx] = _lifespan;
|
|
||||||
randOffset.x = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength;
|
|
||||||
randOffset.y = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength;
|
|
||||||
randOffset.z = (((double)rand() / (double)RAND_MAX) - 0.5) * 0.25 * _emitStrength;
|
|
||||||
_paVelocity[j] = (_emitDirection.x * _emitStrength) + randOffset.x;
|
|
||||||
_paVelocity[j + 1] = (_emitDirection.y * _emitStrength) + randOffset.y;
|
|
||||||
_paVelocity[j + 2] = (_emitDirection.z * _emitStrength) + randOffset.z;
|
|
||||||
|
|
||||||
// DUMB FORWARD EULER just to get it done
|
timeLeftInFrame -= _timeUntilNextEmit;
|
||||||
_paPosition[j] += _paVelocity[j] * deltaTime;
|
_timeUntilNextEmit = 1.0f / _emitRate;
|
||||||
_paPosition[j + 1] += _paVelocity[j + 1] * deltaTime;
|
|
||||||
_paPosition[j + 2] += _paVelocity[j + 2] * deltaTime;
|
|
||||||
|
|
||||||
_paXmin = glm::min(_paXmin, _paPosition[j]);
|
// emit a new particle at tail index.
|
||||||
_paYmin = glm::min(_paYmin, _paPosition[j + 1]);
|
quint32 i = _particleTailIndex;
|
||||||
_paZmin = glm::min(_paZmin, _paPosition[j + 2]);
|
_particleLifetimes[i] = _lifespan;
|
||||||
_paXmax = glm::max(_paXmax, _paPosition[j]);
|
|
||||||
_paYmax = glm::max(_paYmax, _paPosition[j + 1]);
|
|
||||||
_paZmax = glm::max(_paZmax, _paPosition[j + 2]);
|
|
||||||
|
|
||||||
// massless particles
|
// jitter the _emitDirection by a random offset
|
||||||
// and simple gravity down
|
glm::vec3 randOffset;
|
||||||
_paVelocity[j + 1] += deltaTime * _localGravity;
|
randOffset.x = (randFloat() - 0.5f) * 0.25f * _emitStrength;
|
||||||
|
randOffset.y = (randFloat() - 0.5f) * 0.25f * _emitStrength;
|
||||||
|
randOffset.z = (randFloat() - 0.5f) * 0.25f * _emitStrength;
|
||||||
|
|
||||||
emitIdx = (emitIdx + 1) % _maxParticles;
|
// set initial conditions
|
||||||
_paCount++;
|
_particlePositions[i] = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
_particleVelocities[i] = _emitDirection * _emitStrength + randOffset;
|
||||||
|
|
||||||
|
integrateParticle(i, timeLeftInFrame);
|
||||||
|
extendBounds(_particlePositions[i]);
|
||||||
|
|
||||||
|
_particleTailIndex = (_particleTailIndex + 1) % _maxParticles;
|
||||||
|
|
||||||
|
// overflow! move head forward by one.
|
||||||
|
// because the case of head == tail indicates an empty array, not a full one.
|
||||||
|
// This can drop an existing older particle, but this is by design, newer particles are a higher priority.
|
||||||
|
if (_particleTailIndex == _particleHeadIndex) {
|
||||||
|
_particleHeadIndex = (_particleHeadIndex + 1) % _maxParticles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
break;
|
_timeUntilNextEmit -= timeLeftInFrame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParticleEffectEntityItem::resetSimulation() {
|
void ParticleEffectEntityItem::setMaxParticles(quint32 maxParticles) {
|
||||||
for (quint32 i = 0; i < _maxParticles; i++) {
|
_maxParticles = maxParticles;
|
||||||
quint32 j = i * XYZ_STRIDE;
|
|
||||||
_paLife[i] = -1.0f;
|
|
||||||
_paPosition[j] = 0.0f;
|
|
||||||
_paPosition[j+1] = 0.0f;
|
|
||||||
_paPosition[j+2] = 0.0f;
|
|
||||||
_paVelocity[j] = 0.0f;
|
|
||||||
_paVelocity[j+1] = 0.0f;
|
|
||||||
_paVelocity[j+2] = 0.0f;
|
|
||||||
}
|
|
||||||
_paCount = 0;
|
|
||||||
_paHead = 0;
|
|
||||||
_partialEmit = 0.0f;
|
|
||||||
|
|
||||||
srand(_randSeed);
|
// TODO: try to do something smart here and preserve the state of existing particles.
|
||||||
|
|
||||||
|
// resize vectors
|
||||||
|
_particleLifetimes.resize(_maxParticles);
|
||||||
|
_particlePositions.resize(_maxParticles);
|
||||||
|
_particleVelocities.resize(_maxParticles);
|
||||||
|
|
||||||
|
// effectivly clear all particles and start emitting new ones from scratch.
|
||||||
|
_particleHeadIndex = 0;
|
||||||
|
_particleTailIndex = 0;
|
||||||
|
_timeUntilNextEmit = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// because particles are in a ring buffer, this isn't trivial
|
||||||
|
quint32 ParticleEffectEntityItem::getLivingParticleCount() const {
|
||||||
|
if (_particleTailIndex >= _particleHeadIndex) {
|
||||||
|
return _particleTailIndex - _particleHeadIndex;
|
||||||
|
} else {
|
||||||
|
return (_maxParticles - _particleHeadIndex) + _particleTailIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,29 +2,6 @@
|
||||||
// ParticleEffectEntityItem.h
|
// ParticleEffectEntityItem.h
|
||||||
// libraries/entities/src
|
// libraries/entities/src
|
||||||
//
|
//
|
||||||
// Some starter code for a particle simulation entity, which could ideally be used for a variety of effects.
|
|
||||||
// This is some really early and rough stuff here. It was enough for now to just get it up and running in the interface.
|
|
||||||
//
|
|
||||||
// Todo's and other notes:
|
|
||||||
// - The simulation should restart when the AnimationLoop's max frame is reached (or passed), but there doesn't seem
|
|
||||||
// to be a good way to set that max frame to something reasonable right now.
|
|
||||||
// - There seems to be a bug whereby entities on the edge of screen will just pop off or on. This is probably due
|
|
||||||
// to my lack of understanding of how entities in the octree are picked for rendering. I am updating the entity
|
|
||||||
// dimensions based on the bounds of the sim, but maybe I need to update a dirty flag or something.
|
|
||||||
// - This should support some kind of pre-roll of the simulation.
|
|
||||||
// - Just to get this out the door, I just did forward Euler integration. There are better ways.
|
|
||||||
// - Gravity always points along the Y axis. Support an actual gravity vector.
|
|
||||||
// - Add the ability to add arbitrary forces to the simulation.
|
|
||||||
// - Add controls for spread (which is currently hard-coded) and varying emission strength (not currently implemented).
|
|
||||||
// - Add drag.
|
|
||||||
// - Add some kind of support for collisions.
|
|
||||||
// - For simplicity, I'm currently just rendering each particle as a cross of four axis-aligned quads. Really, we'd
|
|
||||||
// want multiple render modes, including (the most important) textured billboards (always facing camera). Also, these
|
|
||||||
// should support animated textures.
|
|
||||||
// - There's no synchronization of the simulation across clients at all. In fact, it's using rand() under the hood, so
|
|
||||||
// there's no gaurantee that different clients will see simulations that look anything like the other.
|
|
||||||
// - MORE?
|
|
||||||
//
|
|
||||||
// Created by Jason Rickwald on 3/2/15.
|
// Created by Jason Rickwald on 3/2/15.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
@ -39,14 +16,14 @@
|
||||||
|
|
||||||
class ParticleEffectEntityItem : public EntityItem {
|
class ParticleEffectEntityItem : public EntityItem {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||||
|
|
||||||
ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
ParticleEffectEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
|
||||||
virtual ~ParticleEffectEntityItem();
|
virtual ~ParticleEffectEntityItem();
|
||||||
|
|
||||||
ALLOW_INSTANTIATION // This class can be instantiated
|
ALLOW_INSTANTIATION // This class can be instantiated
|
||||||
|
|
||||||
// methods for getting/setting all properties of this entity
|
// methods for getting/setting all properties of this entity
|
||||||
virtual EntityItemProperties getProperties() const;
|
virtual EntityItemProperties getProperties() const;
|
||||||
virtual bool setProperties(const EntityItemProperties& properties);
|
virtual bool setProperties(const EntityItemProperties& properties);
|
||||||
|
@ -54,16 +31,16 @@ public:
|
||||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||||
|
|
||||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||||
EntityPropertyFlags& requestedProperties,
|
EntityPropertyFlags& requestedProperties,
|
||||||
EntityPropertyFlags& propertyFlags,
|
EntityPropertyFlags& propertyFlags,
|
||||||
EntityPropertyFlags& propertiesDidntFit,
|
EntityPropertyFlags& propertiesDidntFit,
|
||||||
int& propertyCount,
|
int& propertyCount,
|
||||||
OctreeElement::AppendState& appendState) const;
|
OctreeElement::AppendState& appendState) const;
|
||||||
|
|
||||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||||
ReadBitstreamToTreeParams& args,
|
ReadBitstreamToTreeParams& args,
|
||||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||||
|
|
||||||
virtual void update(const quint64& now);
|
virtual void update(const quint64& now);
|
||||||
virtual bool needsToCallUpdate() const;
|
virtual bool needsToCallUpdate() const;
|
||||||
|
@ -71,6 +48,7 @@ public:
|
||||||
const rgbColor& getColor() const { return _color; }
|
const rgbColor& getColor() const { return _color; }
|
||||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||||
|
|
||||||
|
static const xColor DEFAULT_COLOR;
|
||||||
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); }
|
||||||
void setColor(const xColor& value) {
|
void setColor(const xColor& value) {
|
||||||
_color[RED_INDEX] = value.red;
|
_color[RED_INDEX] = value.red;
|
||||||
|
@ -109,7 +87,7 @@ public:
|
||||||
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
|
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||||
|
|
||||||
static const quint32 DEFAULT_MAX_PARTICLES;
|
static const quint32 DEFAULT_MAX_PARTICLES;
|
||||||
void setMaxParticles(quint32 maxParticles) { _maxParticles = maxParticles; }
|
void setMaxParticles(quint32 maxParticles);
|
||||||
quint32 getMaxParticles() const { return _maxParticles; }
|
quint32 getMaxParticles() const { return _maxParticles; }
|
||||||
|
|
||||||
static const float DEFAULT_LIFESPAN;
|
static const float DEFAULT_LIFESPAN;
|
||||||
|
@ -121,7 +99,7 @@ public:
|
||||||
float getEmitRate() const { return _emitRate; }
|
float getEmitRate() const { return _emitRate; }
|
||||||
|
|
||||||
static const glm::vec3 DEFAULT_EMIT_DIRECTION;
|
static const glm::vec3 DEFAULT_EMIT_DIRECTION;
|
||||||
void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = emitDirection; }
|
void setEmitDirection(glm::vec3 emitDirection) { _emitDirection = glm::normalize(emitDirection); }
|
||||||
const glm::vec3& getEmitDirection() const { return _emitDirection; }
|
const glm::vec3& getEmitDirection() const { return _emitDirection; }
|
||||||
|
|
||||||
static const float DEFAULT_EMIT_STRENGTH;
|
static const float DEFAULT_EMIT_STRENGTH;
|
||||||
|
@ -141,11 +119,22 @@ public:
|
||||||
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
||||||
QString getAnimationSettings() const;
|
QString getAnimationSettings() const;
|
||||||
|
|
||||||
|
static const QString DEFAULT_TEXTURES;
|
||||||
|
const QString& getTextures() const { return _textures; }
|
||||||
|
void setTextures(const QString& textures) {
|
||||||
|
if (_textures != textures) {
|
||||||
|
_textures = textures;
|
||||||
|
_texturesChangedFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool isAnimatingSomething() const;
|
bool isAnimatingSomething() const;
|
||||||
void stepSimulation(float deltaTime);
|
void stepSimulation(float deltaTime);
|
||||||
void resetSimulation();
|
void extendBounds(const glm::vec3& point);
|
||||||
|
void integrateParticle(quint32 index, float deltaTime);
|
||||||
|
quint32 getLivingParticleCount() const;
|
||||||
|
|
||||||
// the properties of this entity
|
// the properties of this entity
|
||||||
rgbColor _color;
|
rgbColor _color;
|
||||||
|
@ -159,25 +148,24 @@ protected:
|
||||||
quint64 _lastAnimated;
|
quint64 _lastAnimated;
|
||||||
AnimationLoop _animationLoop;
|
AnimationLoop _animationLoop;
|
||||||
QString _animationSettings;
|
QString _animationSettings;
|
||||||
|
QString _textures;
|
||||||
|
bool _texturesChangedFlag;
|
||||||
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
||||||
|
|
||||||
// all the internals of running the particle sim
|
// all the internals of running the particle sim
|
||||||
const quint32 XYZ_STRIDE = 3;
|
QVector<float> _particleLifetimes;
|
||||||
float* _paLife;
|
QVector<glm::vec3> _particlePositions;
|
||||||
float* _paPosition;
|
QVector<glm::vec3> _particleVelocities;
|
||||||
float* _paVelocity;
|
float _timeUntilNextEmit;
|
||||||
float _partialEmit;
|
|
||||||
quint32 _paCount;
|
|
||||||
quint32 _paHead;
|
|
||||||
float _paXmin;
|
|
||||||
float _paXmax;
|
|
||||||
float _paYmin;
|
|
||||||
float _paYmax;
|
|
||||||
float _paZmin;
|
|
||||||
float _paZmax;
|
|
||||||
unsigned int _randSeed;
|
|
||||||
|
|
||||||
|
// particle arrays are a ring buffer, use these indicies
|
||||||
|
// to keep track of the living particles.
|
||||||
|
quint32 _particleHeadIndex;
|
||||||
|
quint32 _particleTailIndex;
|
||||||
|
|
||||||
|
// bounding volume
|
||||||
|
glm::vec3 _particleMaxBound;
|
||||||
|
glm::vec3 _particleMinBound;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ParticleEffectEntityItem_h
|
#endif // hifi_ParticleEffectEntityItem_h
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,6 @@ void SimpleEntitySimulation::removeEntityInternal(EntityItem* entity) {
|
||||||
_hasSimulationOwnerEntities.remove(entity);
|
_hasSimulationOwnerEntities.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITIES | EntityItem::DIRTY_MOTION_TYPE;
|
|
||||||
|
|
||||||
void SimpleEntitySimulation::changeEntityInternal(EntityItem* entity) {
|
void SimpleEntitySimulation::changeEntityInternal(EntityItem* entity) {
|
||||||
EntitySimulation::changeEntityInternal(entity);
|
EntitySimulation::changeEntityInternal(entity);
|
||||||
if (!entity->getSimulatorID().isNull()) {
|
if (!entity->getSimulatorID().isNull()) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <qcompilerdetection.h>
|
||||||
|
|
||||||
#include "SkyFromAtmosphere_vert.h"
|
#include "SkyFromAtmosphere_vert.h"
|
||||||
#include "SkyFromAtmosphere_frag.h"
|
#include "SkyFromAtmosphere_frag.h"
|
||||||
|
@ -292,17 +293,19 @@ void SunSkyStage::updateGraphicsObject() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
switch (getBackgroundMode()) {
|
switch (getBackgroundMode()) {
|
||||||
case NO_BACKGROUND: {
|
case NO_BACKGROUND: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SKY_DOME: {
|
case SKY_DOME: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SKY_BOX: {
|
case SKY_BOX: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
case NUM_BACKGROUND_MODES:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
};
|
||||||
|
|
||||||
static int firstTime = 0;
|
static int firstTime = 0;
|
||||||
if (firstTime == 0) {
|
if (firstTime == 0) {
|
||||||
|
|
|
@ -38,9 +38,10 @@ public:
|
||||||
~TextureStorage();
|
~TextureStorage();
|
||||||
|
|
||||||
const QUrl& getUrl() const { return _url; }
|
const QUrl& getUrl() const { return _url; }
|
||||||
const gpu::Texture::Type getType() const { return _usage._type; }
|
gpu::Texture::Type getType() const { return _usage._type; }
|
||||||
const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; }
|
const gpu::TexturePointer& getGPUTexture() const { return _gpuTexture; }
|
||||||
|
|
||||||
|
virtual void reset() { Storage::reset(); }
|
||||||
void reset(const QUrl& url, const TextureUsage& usage);
|
void reset(const QUrl& url, const TextureUsage& usage);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -72,7 +72,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
return 1;
|
return 1;
|
||||||
case PacketTypeEntityAddOrEdit:
|
case PacketTypeEntityAddOrEdit:
|
||||||
case PacketTypeEntityData:
|
case PacketTypeEntityData:
|
||||||
return VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY;
|
return VERSION_ENTITIES_PARTICLE_ENTITIES_HAVE_TEXTURES;
|
||||||
case PacketTypeEntityErase:
|
case PacketTypeEntityErase:
|
||||||
return 2;
|
return 2;
|
||||||
case PacketTypeAudioStreamStats:
|
case PacketTypeAudioStreamStats:
|
||||||
|
|
|
@ -173,5 +173,6 @@ const PacketVersion VERSION_ENTITIES_HAVE_NAMES = 19;
|
||||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20;
|
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_ATMOSPHERE = 20;
|
||||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21;
|
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_SKYBOX = 21;
|
||||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY = 22;
|
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_STAGE_HAS_AUTOMATIC_HOURDAY = 22;
|
||||||
|
const PacketVersion VERSION_ENTITIES_PARTICLE_ENTITIES_HAVE_TEXTURES = 23;
|
||||||
|
|
||||||
#endif // hifi_PacketHeaders_h
|
#endif // hifi_PacketHeaders_h
|
||||||
|
|
|
@ -721,6 +721,76 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color) {
|
||||||
|
BatchItemDetails& details = _registeredVertices[id];
|
||||||
|
|
||||||
|
if (details.isCreated) {
|
||||||
|
details.clear();
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED";
|
||||||
|
#endif // def WANT_DEBUG
|
||||||
|
}
|
||||||
|
|
||||||
|
const int FLOATS_PER_VERTEX = 5;
|
||||||
|
details.isCreated = true;
|
||||||
|
details.vertices = points.size();
|
||||||
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
|
|
||||||
|
gpu::BufferPointer verticesBuffer(new gpu::Buffer());
|
||||||
|
gpu::BufferPointer colorBuffer(new gpu::Buffer());
|
||||||
|
gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format());
|
||||||
|
gpu::BufferStreamPointer stream(new gpu::BufferStream());
|
||||||
|
|
||||||
|
details.verticesBuffer = verticesBuffer;
|
||||||
|
details.colorBuffer = colorBuffer;
|
||||||
|
details.streamFormat = streamFormat;
|
||||||
|
details.stream = stream;
|
||||||
|
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), 3 * sizeof(float));
|
||||||
|
details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA));
|
||||||
|
|
||||||
|
details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
|
||||||
|
details.stream->addBuffer(details.colorBuffer, 0, details.streamFormat->getChannels().at(1)._stride);
|
||||||
|
|
||||||
|
assert(points.size() == texCoords.size());
|
||||||
|
|
||||||
|
details.vertices = points.size();
|
||||||
|
details.vertexSize = FLOATS_PER_VERTEX;
|
||||||
|
|
||||||
|
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||||
|
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||||
|
((int(color.z * 255.0f) & 0xFF) << 16) |
|
||||||
|
((int(color.w * 255.0f) & 0xFF) << 24);
|
||||||
|
|
||||||
|
GLfloat* vertexData = new GLfloat[details.vertices * FLOATS_PER_VERTEX];
|
||||||
|
GLfloat* vertex = vertexData;
|
||||||
|
|
||||||
|
int* colorData = new int[details.vertices];
|
||||||
|
int* colorDataAt = colorData;
|
||||||
|
|
||||||
|
for (int i = 0; i < points.size(); i++) {
|
||||||
|
glm::vec3 point = points[i];
|
||||||
|
glm::vec2 texCoord = texCoords[i];
|
||||||
|
*(vertex++) = point.x;
|
||||||
|
*(vertex++) = point.y;
|
||||||
|
*(vertex++) = point.z;
|
||||||
|
*(vertex++) = texCoord.x;
|
||||||
|
*(vertex++) = texCoord.y;
|
||||||
|
|
||||||
|
*(colorDataAt++) = compactColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
details.verticesBuffer->append(sizeof(GLfloat) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*) vertexData);
|
||||||
|
details.colorBuffer->append(sizeof(int) * details.vertices, (gpu::Byte*) colorData);
|
||||||
|
delete[] vertexData;
|
||||||
|
delete[] colorData;
|
||||||
|
|
||||||
|
#ifdef WANT_DEBUG
|
||||||
|
qCDebug(renderutils) << "new registered linestrip buffer made -- _registeredVertices.size():" << _registeredVertices.size();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) {
|
void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) {
|
||||||
BatchItemDetails& details = _registeredVertices[id];
|
BatchItemDetails& details = _registeredVertices[id];
|
||||||
if (details.isCreated) {
|
if (details.isCreated) {
|
||||||
|
|
|
@ -198,6 +198,7 @@ public:
|
||||||
|
|
||||||
void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color);
|
void updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color);
|
||||||
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
|
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
|
||||||
|
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
|
||||||
void renderVertices(gpu::Primitive primitiveType, int id);
|
void renderVertices(gpu::Primitive primitiveType, int id);
|
||||||
|
|
||||||
/// Loads geometry from the specified URL.
|
/// Loads geometry from the specified URL.
|
||||||
|
|
|
@ -117,18 +117,6 @@ void GlowEffect::end() {
|
||||||
glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop());
|
glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maybeBind(const gpu::FramebufferPointer& fbo) {
|
|
||||||
if (fbo) {
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(fbo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void maybeRelease(const gpu::FramebufferPointer& fbo) {
|
|
||||||
if (fbo) {
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu::FramebufferPointer GlowEffect::render() {
|
gpu::FramebufferPointer GlowEffect::render() {
|
||||||
PerformanceTimer perfTimer("glowEffect");
|
PerformanceTimer perfTimer("glowEffect");
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
|
#include "AABox.h"
|
||||||
#include "Extents.h"
|
#include "Extents.h"
|
||||||
|
|
||||||
void Extents::reset() {
|
void Extents::reset() {
|
||||||
|
@ -37,6 +38,11 @@ void Extents::addPoint(const glm::vec3& point) {
|
||||||
maximum = glm::max(maximum, point);
|
maximum = glm::max(maximum, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Extents::add(const AABox& box) {
|
||||||
|
minimum = glm::min(minimum, box.getMinimumPoint());
|
||||||
|
maximum = glm::max(maximum, box.getMaximumPoint());
|
||||||
|
}
|
||||||
|
|
||||||
void Extents::rotate(const glm::quat& rotation) {
|
void Extents::rotate(const glm::quat& rotation) {
|
||||||
glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z);
|
glm::vec3 bottomLeftNear(minimum.x, minimum.y, minimum.z);
|
||||||
glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z);
|
glm::vec3 bottomRightNear(maximum.x, minimum.y, minimum.z);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "StreamUtils.h"
|
#include "StreamUtils.h"
|
||||||
|
|
||||||
|
class AABox;
|
||||||
|
|
||||||
class Extents {
|
class Extents {
|
||||||
public:
|
public:
|
||||||
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
|
/// set minimum and maximum to FLT_MAX and -FLT_MAX respectively
|
||||||
|
@ -28,6 +30,10 @@ public:
|
||||||
/// expand current limits to contain other extents
|
/// expand current limits to contain other extents
|
||||||
void addExtents(const Extents& extents);
|
void addExtents(const Extents& extents);
|
||||||
|
|
||||||
|
/// \param aabox another intance of extents
|
||||||
|
/// expand current limits to contain other aabox
|
||||||
|
void add(const AABox& box);
|
||||||
|
|
||||||
/// \param point new point to compare against existing limits
|
/// \param point new point to compare against existing limits
|
||||||
/// compare point to current limits and expand them if necessary to contain point
|
/// compare point to current limits and expand them if necessary to contain point
|
||||||
void addPoint(const glm::vec3& point);
|
void addPoint(const glm::vec3& point);
|
||||||
|
|
Loading…
Reference in a new issue